java 使用图片代理程序,解决网站图片防盗链机制(测试百度,QQ空间有效)
2018-03-22 15:55
736 查看
业务场景
1、页面引用其他站点图片的时候,由于某些站点存在图片的防盗链机制,所以在引用图片的时候,返回的一张默认的图片,而不是原图片。2、使用java完成一个代理程序,代理所有的存在防盗链机制的图片请求,绕过防盗链机制,返回原图片
解决思路
1、代理请求传输的http头信息Host,使用图片url的Host,而自身站点的Host地址2、代理请求传输的http头信息Referer,使用图片url的Host,前面加上”http://”
3、完成以上1、2的操作,用以模拟图片本身站点对图片的请求,绕过反防盗链机制
代理相关的工具类
当中使用了Apache Commons IO,解决的网络图片获取不完整的bug(需要的包请点击下载)package lib; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; import org.apache.commons.io.IOUtils; import com.mysql.jdbc.StringUtils; import dto.ImageData; /** * 用于获取url的图片数据 * @author yuyu * */ public class GetProxyImage { /** * 根据传入的url将结果以byte[]的数据返回 * @param url 需要请求的url * @return * @throws Exception */ public static ImageData getImage(String url)throws Exception{ //当传入的url返回不为空的时候,读取数据 ImageData back=null; InputStream input; if(!StringUtils.isNullOrEmpty(url)){ try{ back =new ImageData(); String ContentType=null; //设置请求的头信息 URL urlInfo = new URL(url); URLConnection connection = urlInfo.openConnection(); //设置头信息 connection.addRequestProperty("Host", urlInfo.getHost()); connection.addRequestProperty("Connection", "keep-alive"); //强制要求缓存服务器在返回缓存的版本之前将请求提交到源头服务器进行验证。 connection.addRequestProperty("Cache-Control", "no-cache"); //使用url的Host来标记来源 connection.addRequestProperty("Referer", "http://"+urlInfo.getHost()); //表示用户不愿意目标站点追踪用户个人信息。 connection.addRequestProperty("DNT", "1"); //强制要求缓存服务器在返回缓存的版本之前将请求提交到源头服务器进行验证。 connection.addRequestProperty("Pragma", "no-cache"); connection.addRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"); connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36"); connection.connect(); //获取头信息,图片的返回格式 Map<String, List<String>> map = connection.getHeaderFields(); List<String> type=map.get("Content-Type"); ContentType=type.get(0); //获取请求回来的信息 input = connection.getInputStream(); //解决使用inputStream.available(),读取图片不完整问题 //此方法在内部缓冲输入,因此不需要使用BufferedInputStream。 byte[]data = IOUtils.toByteArray(input); input.close(); //设置返回信息 back.setContentType(ContentType); back.setData(data); }catch(Exception e){ throw new Exception("读取Url数据失败:"+url,e); } } return back; } }
用以传输图片对象的简单类
package dto; /** * 用于http图片数据请求 * @author yuyu * */ public class ImageData { //图片返回的格式信息 private String ContentType; //图片返回数据的字节数组 private byte[] data; public String getContentType() { return ContentType; } public void setContentType(String contentType) { ContentType = contentType; } public byte[] getData() { return data; } public void setData(byte[] data) { this.data = data; } @Override public String toString() { return "ImageData [ContentType=" + ContentType + ", data长度=" + data.length + "]"; } }
处理代理请求的Servlet
package proxyImage; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import dto.ImageData; import lib.GetProxyImage; @SuppressWarnings("serial") public class ProxyImage extends HttpServlet { /** * 接收一个代理图片的url,返回代理得来的图片数据 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String url=request.getParameter("url"); //获取图片信息 try { ImageData image = GetProxyImage.getIm e82c age(url); System.out.println(image); if(image!=null){ //将获取到的图片返回 response.setContentType(image.getContentType()); //设置浏览器缓存 response.setHeader("Cache-Control", "max-age=31536000"); OutputStream out = response.getOutputStream(); out.write(image.getData()); out.flush(); out.close(); } } catch (Exception e) { e.printStackTrace(); } } }
展示jsp页面
页面的具体数据绑定使用了vue 框架(详情请点击查看)<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>proxy image page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body style="text-align:center"> <div id="app" > <h2>{{ message }}</h2> <input v-model="imageUrl" style="width: 800px;height: 30px;" Placeholder="请输入图片地址"> <br> <div style="display: inline-block;"> <h5>原图片</h5> <img :src="imageUrl" style="width: 400px;height: 300px;"> </div> <div style="display: inline-block;"> <h5>代理图片</h5> <img :src="proxyImageUrl" style="width: 400px;height: 300px;"> </div> </div> <script> var app = new Vue({ el: '#app', data: { message: '图片代理展示', imageUrl: '' }, computed: { proxyImageUrl: function () { return 'servlet/ProxyImage?url='+encodeURIComponent(this.imageUrl) } } }) </script> </body> </html>
测试
一、百度1、从百度引用的图片地址:
http://a.hiphotos.baidu.com/image/w%3D230/sign=fa52b971b1de9c82a665fe8c5c8180d2/d53f8794a4c27d1eba11668c19d5ad6eddc43846.jpg
2、代理截图:
二、QQ空间
1、从QQ空间引用的图片地址:
http://a4.qpic.cn/psb?/f2006c66-5773-4a59-8984-2cbea031e9c0/WB*zO7jU3cQhrGgLSKf9Vd5c.YNcq67BGOWQmdO1qkk!/m/dEMBAAAAAAAA
2、代理截图:
总结
1、如果代理的图片过大,或者过于频繁其实可以将代理的结果缓存起来2、这个代理程序只适合于其他站点的静态图片获取,要是动态的隐私图片可能会根据登入用户的cookie或者ip显示,这个时候就会代理失败
相关文章推荐
- 如何使用Proxy模式及Java内建的动态代理机制
- Java中使用MySQL从安装、配置到实际程序测试详解
- 使用squid代理后某些网站无法访问的解决办法
- asp破解(百度,网易,新浪,搜狐,QQ空间)图片防盗链代码
- asp.net网站图片防盗链机制示例代码
- 如何使用Proxy模式及Java内建的动态代理机制
- 使用java的代理机制实现日志的输出
- 使用JSmooth将java程序转换成windows上的.exe文件(彻底解决相对目录问题)
- 使用JDBC和Hibernate在oracle中插入和读取Blob数据的图片的java程序
- Asp.net网站使用HttpHandler实现图片防盗链功能
- 使用Java的代理机制进行日志输出
- Java中使用MySQL从安装、配置到实际程序测试详解
- 使用JSmooth将java程序转换成windows上的.exe文件(彻底解决相对目录问题)
- 解决使用路由器上传网站出现FTP上传缓慢至0.0kb/s的解决办法(实测有效)
- 又一次闲来无聊,使用Java的动态代理机制来模拟AOP
- 如何使用Proxy模式及Java内建的动态代理机制
- 使用Java的代理机制进行日志输出(存疑)
- 烂泥:使用火狐解决网站图片不能复制下载的问题
- 使用Java的代理机制进行日志输出
- asp破解(百度,网易,新浪,搜狐,QQ空间)图片防盗链代码