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. HDU_2084_DP

    http://acm.hdu.edu.cn/showproblem.php?pid=2084 简单dp,从下到上,从左到右,依次更新每个位置最大值. #include<iostream> ...

  2. HDU4195 Regular Convex Polygon (正多边形、外接圆)

    题意: 给你正n边形上的三个点,问n最少为多少 思路: 三个点在多边形上,所以三个点的外接圆就是这个正多边形的外接圆,余弦定理求出每个角的弧度值,即该角所对边的圆周角,该边对应的圆心角为圆心角的二倍. ...

  3. C语言寒假大作战04

    问题 答案 这个作业属于那个课程 https://edu.cnblogs.c0m/campus/zswxy/CST2019-4 这个作业的要求在哪里 https://edu.cnblogs.com/c ...

  4. python学习(5)写一个二分算法的程序

    把之前学习的做一个小结.之前看二分查找法,只能是似而非地看懂大概.现在用这么多天的知识积累已经可以自己写了. 而且在算法书的基础上,把需要找的数字做一个人机互动操作. 另外,初步接触到了 __name ...

  5. javascript 浅复制 和 深复制

    如何区分深拷贝与浅拷贝,简单点来说,就是假设 B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝, 如果B没变,那就是深拷贝 实现思路 1 json 深度拷贝 2 遍历递归 ...

  6. objectarx 多段线自交检查

    只支持直线段的多段线检查,因为主要用了初中的知识,一元一次方程求交点,详细的说就是,把多段线上相邻的两个点构成一条直线段,然后每条直线段与剩余的直线段求交点,一条直线段就代表一个一元一次方程,知道两点 ...

  7. 大延时情况tcp和udp测试

    环境搭建 使能Ubuntu的IPv6转发功能 root@yanhc-Aspire-4738G:/home/yanhc# cat /proc/sys/net/ipv4/ip_forward root@y ...

  8. 如何在 Linux 中找出 CPU 占用高的进程

    1) 怎样使用 top 命令找出 Linux 中 CPU 占用高的进程 在所有监控 Linux 系统性能的工具中,Linux 的 top 命令是最好的也是最知名的一个.top 命令提供了 Linux ...

  9. Ubuntu14.04安装及配置mysql5.7.19

    通过uname -a或lsb_release -a 查看版本信息 ,确定linux的发行版是debian还是ubuntu.root@suepc:/usr/local# uname -aLinux su ...

  10. 【转载】STM32 ST-LINK Utility介绍、下载、安装、使用方法

    转载地址:https://blog.csdn.net/ybhuangfugui/article/details/52597133 总结的很好!!! Ⅰ.写在前面本文讲述的内容是STM32 ST-LIN ...