CSRF(具体参考百度百科)

CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

具体思路:

1、跳转页面前生成随机token,并存放在session中

2、form中将token放在隐藏域中,保存时将token放头部一起提交

3、获取头部token,与session中的token比较,一致则通过,否则不予提交

4、生成新的token,并传给前端

1、拦截器配置

	<mvc:interceptors>
<!-- csrf攻击防御 -->
<mvc:interceptor>
<!-- 需拦截的地址 -->
<mvc:mapping path="/**" />
<!-- 需排除拦截的地址 -->
<mvc:exclude-mapping path="/resources/**" />
<bean class="com.cnpc.framework.interceptor.CSRFInterceptor" />
</mvc:interceptor>
</mvc:interceptors>

2拦截器实现 CSRFInterceptor.java

package com.cnpc.framework.interceptor;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.alibaba.fastjson.JSONObject;
import com.cnpc.framework.annotation.RefreshCSRFToken;
import com.cnpc.framework.annotation.VerifyCSRFToken;
import com.cnpc.framework.base.pojo.ResultCode;
import com.cnpc.framework.constant.CodeConstant;
import com.cnpc.framework.utils.CSRFTokenUtil;
import com.cnpc.framework.utils.StrUtil; /**
* CSRFInterceptor 防止跨站请求伪造拦截器
*
* @author billJiang 2016年10月6日 下午8:14:40
*/
public class CSRFInterceptor extends HandlerInterceptorAdapter { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("---------->" + request.getRequestURI());
System.out.println(request.getHeader("X-Requested-With"));
// 提交表单token 校验
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
VerifyCSRFToken verifyCSRFToken = method.getAnnotation(VerifyCSRFToken.class);
// 如果配置了校验csrf token校验,则校验
if (verifyCSRFToken != null) {
// 是否为Ajax标志
String xrq = request.getHeader("X-Requested-With");
// 非法的跨站请求校验
if (verifyCSRFToken.verify() && !verifyCSRFToken(request)) {
if (StrUtil.isEmpty(xrq)) {
// form表单提交,url get方式,刷新csrftoken并跳转提示页面
String csrftoken = CSRFTokenUtil.generate(request);
request.getSession().setAttribute("CSRFToken", csrftoken);
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("非法请求");
response.flushBuffer();
return false;
} else {
// 刷新CSRFToken,返回错误码,用于ajax处理,可自定义
String csrftoken = CSRFTokenUtil.generate(request);
request.getSession().setAttribute("CSRFToken", csrftoken);
ResultCode rc = CodeConstant.CSRF_ERROR;
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print(JSONObject.toJSONString(rc));
response.flushBuffer();
return false;
}
} }
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception { // 第一次生成token
if (modelAndView != null) {
if (request.getSession(false) == null || StrUtil.isEmpty((String) request.getSession(false).getAttribute("CSRFToken"))) {
request.getSession().setAttribute("CSRFToken", CSRFTokenUtil.generate(request));
return;
}
}
// 刷新token
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RefreshCSRFToken refreshAnnotation = method.getAnnotation(RefreshCSRFToken.class); // 跳转到一个新页面 刷新token
String xrq = request.getHeader("X-Requested-With");
if (refreshAnnotation != null && refreshAnnotation.refresh() && StrUtil.isEmpty(xrq)) {
request.getSession().setAttribute("CSRFToken", CSRFTokenUtil.generate(request));
return;
} // 校验成功 刷新token 可以防止重复提交
VerifyCSRFToken verifyAnnotation = method.getAnnotation(VerifyCSRFToken.class);
if (verifyAnnotation != null) {
if (verifyAnnotation.verify()) {
if (StrUtil.isEmpty(xrq)) {
request.getSession().setAttribute("CSRFToken", CSRFTokenUtil.generate(request));
} else {
Map<String, String> map = new HashMap<String, String>();
map.put("CSRFToken", CSRFTokenUtil.generate(request));
response.setContentType("application/json;charset=UTF-8");
OutputStream out = response.getOutputStream();
out.write((",'csrf':" + JSONObject.toJSONString(map) + "}").getBytes("UTF-8"));
}
}
}
} /**
* 处理跨站请求伪造 针对需要登录后才能处理的请求,验证CSRFToken校验
*
* @param request
*/
protected boolean verifyCSRFToken(HttpServletRequest request) { // 请求中的CSRFToken
String requstCSRFToken = request.getHeader("CSRFToken");
if (StrUtil.isEmpty(requstCSRFToken)) {
return false;
}
String sessionCSRFToken = (String) request.getSession().getAttribute("CSRFToken");
if (StrUtil.isEmpty(sessionCSRFToken)) {
return false;
}
return requstCSRFToken.equals(sessionCSRFToken);
}
}

 3.CSRFTokenUtil.java 生成随机系列号

package com.cnpc.framework.utils;

import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

public class CSRFTokenUtil {

    public static String generate(HttpServletRequest request) {

        return UUID.randomUUID().toString();
} }

  4、ResultCode

package com.cnpc.framework.base.pojo;

public class ResultCode {

    private String code;

    private String message;

    public ResultCode(String code, String message) {

        this.code = code;
this.message = message;
} public String getCode() { return code;
} public void setCode(String code) { this.code = code;
} public String getMessage() { return message;
} public void setMessage(String message) { this.message = message;
} }

  5、CodeConstant.java

package com.cnpc.framework.constant;

import com.cnpc.framework.base.pojo.ResultCode;

public class CodeConstant {

    public final static ResultCode CSRF_ERROR = new ResultCode("101", "CSRF ERROR:无效的token,或者token过期");
}

  6、ajax提交方法

function ajaxPost(url, params, callback) {
var result = null;
var headers={};
headers['CSRFToken']=$("#csrftoken").val(); $.ajax({
type : 'post',
async : false,
url : url,
data : params,
dataType : 'json',
headers:headers,
success : function(data, status) {
result = data;
if(data&&data.code&&data.code=='101'){
modals.error("操作失败,请刷新重试,具体错误:"+data.message);
return false;
}
if (callback) {
callback.call(this, data, status);
}
},
error : function(err, err1, err2) {
if(err && err.readyState && err.readyState == '4'){
var responseBody = err.responseText;
if(responseBody){
responseBody = "{'retData':"+responseBody;
var resJson = eval('(' + responseBody + ')');
$("#csrftoken").val(resJson.csrf.CSRFToken);
this.success(resJson.retData, 200);
}
return ;
}
modals.error({
text : JSON.stringify(err) + '<br/>err1:' + JSON.stringify(err1) + '<br/>err2:' + JSON.stringify(err2),
large : true
});
}
}); return result;
}

  7、form表单配置

<input type='hidden' value='${CSRFToken}' id='csrftoken'>

  8、注解定义

package com.cnpc.framework.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 跨站请求仿照注解 刷新CSRFToken
*
*/
@Target({ java.lang.annotation.ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface RefreshCSRFToken { /**
* 刷新token
*
* @return
*/
public abstract boolean refresh() default true;
}

  9、注解配置

   @RefreshCSRFToken
@RequestMapping(method = RequestMethod.GET, value = "/edit")
private String edit(String id, HttpServletRequest request) { request.setAttribute("id", id);
return "base/user/user_edit";
} @RequestMapping(method = RequestMethod.POST, value = "/get")
@ResponseBody
private User getUser(String id) { return userService.get(User.class, id);
}

  

Spring mvc拦截器防御CSRF攻击的更多相关文章

  1. SSM(spring mvc+spring+mybatis)学习路径——2-2、spring MVC拦截器

    目录 2-2 Spring MVC拦截器 第一章 概述 第二章 Spring mvc拦截器的实现 2-1 拦截器的工作原理 2-2 拦截器的实现 2-3 拦截器的方法介绍 2-4 多个拦截器应用 2- ...

  2. spring mvc 拦截器的使用

    Spring MVC 拦截器的使用 拦截器简介 Spring MVC 中的拦截器(Interceptor)类似于 Servler 中的过滤器(Filter).用于对处理器进行预处理和后处理.常用于日志 ...

  3. 【Java Web开发学习】Spring MVC 拦截器HandlerInterceptor

    [Java Web开发学习]Spring MVC 拦截器HandlerInterceptor 转载:https://www.cnblogs.com/yangchongxing/p/9324119.ht ...

  4. Spring Boot 2.X(九):Spring MVC - 拦截器(Interceptor)

    拦截器 1.简介 Spring MVC 中的拦截器(Interceptor)类似于 Servlet 开发中的过滤器 Filter,它主要用于拦截用户请求并作相应的处理,它也是 AOP 编程思想的体现, ...

  5. Spring MVC拦截器配置

    Spring MVC拦截器配置 (1)自定义拦截器 package learnspringboot.xiao.other; import org.springframework.web.servlet ...

  6. 写的太细了!Spring MVC拦截器的应用,建议收藏再看!

    Spring MVC拦截器 拦截器是Spring MVC中强大的控件,它可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作. 拦截器概述 对于任何优秀的MVC框架, ...

  7. 对于Spring MVC 拦截器的一些了解

    Spring MVC 拦截器的执行顺序 应用场景 假设请求 localhost:8080/ 则要求直接重定向到 localhost:8080/login ; 定义拦截器顺序 permission lo ...

  8. Spring MVC拦截器浅析

    Spring MVC拦截器 重点:Spring MVC的拦截器只会拦截控制器的请求,如果是jsp.js.image.html则会放行. 什么是拦截器 运行在服务器的程序,先于Servlet或JSP之前 ...

  9. spring MVC拦截器01

    spring MVC拦截 作用:身份校验,权限检查,防止非法訪问. 场景:一个bbs系统,用户没有登录就无法发帖或者删除评论; 一个博客系统,没有登录就无法发表博文,无法添加分类,无法删除博文. sp ...

随机推荐

  1. Powershell下git中文乱码

    问题 使用git log查看提交历史, 发现中文的部分出现了乱码, 如图 解决方案 powershell中输入下面的命令 git config --global core.quotepath fals ...

  2. Netty源码分析之ChannelPipeline—入站事件的传播

    之前的文章中我们说过ChannelPipeline作为Netty中的数据管道,负责传递Channel中消息的事件传播,事件的传播分为入站和出站两个方向,分别通知ChannelInboundHandle ...

  3. [python之路]变量和字符编码

    变量和字符编码 #变量##声明变量```#_*_coding:utf-8_*_ name = "Tom"```上述代码声明了一个变量,变量名为: name,变量name的值为:&q ...

  4. HDU 6186 CS Course (连续位运算)

    CS Course Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  5. num11---桥接模式

    比如手机类,有各种类型,比如翻盖.平板等,每一类下又有各个品牌,比如华为,如果新增一个类型,比如折叠屏,或者新增一个手机品牌,苹果,那么会导致 扩展性问题. 这种情况下,应该使用桥接模式. 代码: 创 ...

  6. Linux学习1-云服务器上搭建禅道项目管理工具

    前言 相信各位测试的小伙伴出去面试总会被问到:测试环境怎么搭建?一个中级测试工程师还是对测试环境一无所知的话,面试官会一脸鄙视的,今天我给大家介绍一下最简单的环境部署-—如何在云服务器部署禅道环境. ...

  7. 使用Java实现三个线程交替打印0-74

    使用Java实现三个线程交替打印0-74 题目分析 三个线程交替打印,即3个线程是按顺序执行的.一个线程执行完之后,唤醒下一个线程,然后阻塞,等待被该线程的上一个线程唤醒.执行的顺序是一个环装的队列 ...

  8. C++ 基础--虚构函数

    virtual 函数 示例代码如下: #include <stdio.h> class base { public: virtual void name(){printf("ba ...

  9. 数据算法 --hadoop/spark数据处理技巧 --(15.查找、统计和列出大图中的所有三角形 16.k-mer计数)

    十五.查找.统计和列出大图中的所有三角形 第一步骤的mr: 第二部mr: 找出三角形 第三部:去重 spark: 十六: k-mer计数 spark:

  10. [转载]理解weight decay

    http://blog.sina.com.cn/s/blog_a89e19440102x1el.html