问题描述
在爬取某网站的时候遇到了问题,因为网站的避免CSRF攻击机制,无法获取到目标页面数据,而是跳转到一个默认页面。
关于CSRF
1、CSRF tokens是如何工作(详情请点击查引用源站点)
1、服务器发送给客户端一个token。
2、客户端提交的表单中带着这个token。
3、如果这个token不合法,那么服务器拒绝这个请求。
2、java 站点应对CSRF参考(详情请点击查引用源站点)
3、Laravel中如何避免CSRF攻击(详情请点击查引用源站点)
爬取站点分析
1、在http头信息可见X-CSRF-Token字段
2、X-CSRF-Token来源,meta标签截图
解决思路
1、获取请求前,先去请求一次这个链接地址的Host,在这一次请求中获取Token,以及Cookie
2、用获取到的Token和Cookie作为头信息去请求传入链接地址
3、相当于多请求了一次这个请求链接地址的Host,必须要注意的是确定获取的Host返回头信息中包含有Set-Cookie字段,以及返回的内容中有包含Token的mate标签,存在这两个条件的时候,这个解决流程才可能实现
实现代码
1、获取Cookie与Token
package dto.ajax;
import org.apache.commons.lang3.StringUtils;
import tool.GetUrlData;
import tool.RegexFinder;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
/**
* Created by yuyu on 2018/3/23.
* 获取处理CSRF需要的相关信息
* 原理:
* 每个用户Session生成了一个CSRF Token,
* 该Token可用于验证登录用户和发起请求者是否是同一人,
* 如果不是则请求失败。
*/
public class CsrfToken {
String cookie;//用于请求的站点的cokie
String csrf_token;//用于请求站点的密钥
/**
* 接收一个网站的host,设置接口请求需要的数据
* 1、获取网站请求回来的Set-Cookie字段
* 2、然后获取内容中的密钥
* <meta content="密钥" name="csrf-token" />
*
* @param url
*/
public CsrfToken(String url) {
//校验传输安全
if(StringUtils.isNotBlank(url)){
try{
//设置请求的头信息.获取url的host
String host=new URL(url).getHost();
URLConnection connection= GetUrlData.getConnection("http://"+host,null);
//获取请求回来的信息
String data = GetUrlData.getStringByConnection(connection);
//匹配token
String metaRegex="<meta(.*?)\\/>";
String tokenRegex="content=\"(.*?)\"";
String tokenReplace="content=\"|\"";
String tokenName="csrf-token"