文档章节

Spring3.x通过配置来防范csrf攻击

java梦想家01
 java梦想家01
发布于 2015/10/16 13:24
字数 1683
阅读 1816
收藏 10
点赞 0
评论 0

1. [代码]CsrfTokenManager 用于管理csrfToken相关     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
packagecom.uncle5.pubrub.web.common;
 
importjava.util.UUID;
 
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpSession;
 
publicfinalclassCsrfTokenManager {
 
    // 隐藏域参数名称
    staticfinalString CSRF_PARAM_NAME ="CSRFToken";
 
    // session中csrfToken参数名称
    publicstaticfinalString CSRF_TOKEN_FOR_SESSION_ATTR_NAME = CsrfTokenManager.class
            .getName() +".tokenval";
 
    privateCsrfTokenManager() {
    };
 
    // 在session中创建csrfToken
    publicstaticString createTokenForSession(HttpSession session) {
        String token =null;
 
        synchronized(session) {
            token = (String) session
                    .getAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);
            if(null== token) {
                token = UUID.randomUUID().toString();
                session.setAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME, token);
            }
        }
        returntoken;
    }
 
    publicstaticString getTokenFromRequest(HttpServletRequest request) {
        returnrequest.getParameter(CSRF_PARAM_NAME);
    }
}

2. [代码]CsrfRequestDataValueProcessor 自动创建hidden的csrfToken域的类     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
packagecom.uncle5.pubrub.web.common;
 
importjava.util.Map;
 
importjavax.servlet.http.HttpServletRequest;
 
importorg.springframework.stereotype.Component;
importorg.springframework.web.servlet.support.RequestDataValueProcessor;
 
importcom.google.common.collect.Maps;
 
@Component("requestDataValueProcessor")
publicclassCsrfRequestDataValueProcessorimplementsRequestDataValueProcessor {
 
    @Override
    publicString processAction(HttpServletRequest request, String action) {
        // TODO 暂时原样返回action
        returnaction;
    }
 
    @Override
    publicString processFormFieldValue(HttpServletRequest request,
            String name, String value, String type) {
        // TODO 暂时原样返回value
        returnvalue;
    }
 
    @Override
    publicMap<String, String> getExtraHiddenFields(HttpServletRequest request) {
        //此处是当使用spring的taglib标签<form:form>创建表单时候,增加的隐藏域参数
        Map<String, String> hiddenFields = Maps.newHashMap();
        hiddenFields.put(CsrfTokenManager.CSRF_PARAM_NAME,
                CsrfTokenManager.createTokenForSession(request.getSession()));
 
        returnhiddenFields;
    }
 
    @Override
    publicString processUrl(HttpServletRequest request, String url) {
        // TODO 暂时原样返回url
        returnurl;
    }
 
}

3. [代码]CsrfInterceptor 对于post请求进行拦截,检测csrfToken是否匹配     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
packagecom.uncle5.pubrub.web.security;
 
importjava.net.URLEncoder;
 
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
 
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.util.StringUtils;
importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
importcom.uncle5.pubrub.web.common.CsrfTokenManager;
importcom.uncle5.pubrub.web.common.WebUser;
 
publicclassCsrfInterceptorextendsHandlerInterceptorAdapter {
 
    privatestaticfinalLogger logger = LoggerFactory
            .getLogger(CsrfInterceptor.class);
 
    @Autowired
    WebUser webUser;
 
    @Override
    publicbooleanpreHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler)throwsException {
 
        if("POST".equalsIgnoreCase(request.getMethod())) {
            String CsrfToken = CsrfTokenManager.getTokenFromRequest(request);
            if(CsrfToken ==null
                    || !CsrfToken.equals(request.getSession().getAttribute(
                            CsrfTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME))) {
                String reLoginUrl ="/login?backurl="
                        + URLEncoder.encode(getCurrentUrl(request),"utf-8");
 
                response.sendRedirect(reLoginUrl);
                returnfalse;
            }
        }
 
        returntrue;
    }
 
    privateString getCurrentUrl(HttpServletRequest request) {
        String currentUrl = request.getRequestURL().toString();
        if(!StringUtils.isEmpty(request.getQueryString())) {
            currentUrl +="?"+ request.getQueryString();
        }
 
        returncurrentUrl;
    }
}

4. [代码]springMVC 配置文件,增加需要进行拦截的url     

?
1
2
3
4
5
6
7
8
<!-- 安全拦截用的 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mappingpath="/forum/post"/>
            <mvc:mappingpath="/forum/reply/*"/>
            <beanclass="com.uncle5.pubrub.web.security.CsrfInterceptor"/>
        </mvc:interceptor>       
    </mvc:interceptors>

5. [代码]jsp页面,需要注意的是必须使用spring的form标签     

?
1
2
3
4
5
6
7
8
9
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
 
<divstyle="margin: 0 auto; border: 1px solid orange; width: 80%; height: 400px;">
        <form:formaction="/forum/post"method="post">
            <span>标题:</span><inputtype="text"name="title"id="title">
            <textareaname="content"id="content"rows="30"cols="40"></textarea>
            <inputtype="submit"name="submit"value="submit">
        </form:form>
    </div>

6. [代码]jsp页面 查看源码会发现已经添加上了hidden字段     

?
1
2
3
4
5
6
7
8
<divstyle="margin: 0 auto; border: 1px solid orange; width: 80%; height: 400px;">
        <formid="command"action="/forum/post"method="post">
            <span>标题:</span><inputtype="text"name="title"id="title">
            <textareaname="content"id="content"rows="30"cols="40"></textarea>          
            <inputtype="submit"name="submit"value="submit">
        <inputtype="hidden"name="CSRFToken"value="35afec82-da7b-449e-9ae9-b38664b5af63"/>
</form>
    </div>

7. [代码]相关原理说明     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1.只有当使用spring的form标签时候,才会在渲染jsp页面时候触发
org.springframework.web.servlet.tags.form.FormTag 类中的
 
@Override
    publicintdoEndTag()throwsJspException {
        RequestDataValueProcessor processor = getRequestContext().getRequestDataValueProcessor();
        ServletRequest request =this.pageContext.getRequest();
        if((processor !=null) && (requestinstanceofHttpServletRequest)) {
            writeHiddenFields(processor.getExtraHiddenFields((HttpServletRequest) request));
        }
        this.tagWriter.endTag();
        returnEVAL_PAGE;
    }
该方法会调用上文中所说的CsrfRequestDataValueProcessor中的创建隐藏域的方法getExtraHiddenFields来创建csrfToken隐藏域。
 
2.对相关需要进行防范csrf攻击的post请求地址进行拦截,此处是依赖springMVC中提供的拦截器机制来操作的
<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/forum/post"/>
            <mvc:mapping path="/forum/reply/*"/>
            <beanclass="com.uncle5.pubrub.web.security.CsrfInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
当用户访问"/forum/post"这个请求时候,会直接进入CsrfInterceptor的preHandle方法,此处针对post请求

1. [代码]CsrfTokenManager 用于管理csrfToken相关     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
packagecom.uncle5.pubrub.web.common;
 
importjava.util.UUID;
 
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpSession;
 
publicfinalclassCsrfTokenManager {
 
    // 隐藏域参数名称
    staticfinalString CSRF_PARAM_NAME ="CSRFToken";
 
    // session中csrfToken参数名称
    publicstaticfinalString CSRF_TOKEN_FOR_SESSION_ATTR_NAME = CsrfTokenManager.class
            .getName() +".tokenval";
 
    privateCsrfTokenManager() {
    };
 
    // 在session中创建csrfToken
    publicstaticString createTokenForSession(HttpSession session) {
        String token =null;
 
        synchronized(session) {
            token = (String) session
                    .getAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);
            if(null== token) {
                token = UUID.randomUUID().toString();
                session.setAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME, token);
            }
        }
        returntoken;
    }
 
    publicstaticString getTokenFromRequest(HttpServletRequest request) {
        returnrequest.getParameter(CSRF_PARAM_NAME);
    }
}

2. [代码]CsrfRequestDataValueProcessor 自动创建hidden的csrfToken域的类     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
packagecom.uncle5.pubrub.web.common;
 
importjava.util.Map;
 
importjavax.servlet.http.HttpServletRequest;
 
importorg.springframework.stereotype.Component;
importorg.springframework.web.servlet.support.RequestDataValueProcessor;
 
importcom.google.common.collect.Maps;
 
@Component("requestDataValueProcessor")
publicclassCsrfRequestDataValueProcessorimplementsRequestDataValueProcessor {
 
    @Override
    publicString processAction(HttpServletRequest request, String action) {
        // TODO 暂时原样返回action
        returnaction;
    }
 
    @Override
    publicString processFormFieldValue(HttpServletRequest request,
            String name, String value, String type) {
        // TODO 暂时原样返回value
        returnvalue;
    }
 
    @Override
    publicMap<String, String> getExtraHiddenFields(HttpServletRequest request) {
        //此处是当使用spring的taglib标签<form:form>创建表单时候,增加的隐藏域参数
        Map<String, String> hiddenFields = Maps.newHashMap();
        hiddenFields.put(CsrfTokenManager.CSRF_PARAM_NAME,
                CsrfTokenManager.createTokenForSession(request.getSession()));
 
        returnhiddenFields;
    }
 
    @Override
    publicString processUrl(HttpServletRequest request, String url) {
        // TODO 暂时原样返回url
        returnurl;
    }
 
}

3. [代码]CsrfInterceptor 对于post请求进行拦截,检测csrfToken是否匹配     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
packagecom.uncle5.pubrub.web.security;
 
importjava.net.URLEncoder;
 
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
 
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.util.StringUtils;
importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
importcom.uncle5.pubrub.web.common.CsrfTokenManager;
importcom.uncle5.pubrub.web.common.WebUser;
 
publicclassCsrfInterceptorextendsHandlerInterceptorAdapter {
 
    privatestaticfinalLogger logger = LoggerFactory
            .getLogger(CsrfInterceptor.class);
 
    @Autowired
    WebUser webUser;
 
    @Override
    publicbooleanpreHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler)throwsException {
 
        if("POST".equalsIgnoreCase(request.getMethod())) {
            String CsrfToken = CsrfTokenManager.getTokenFromRequest(request);
            if(CsrfToken ==null
                    || !CsrfToken.equals(request.getSession().getAttribute(
                            CsrfTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME))) {
                String reLoginUrl ="/login?backurl="
                        + URLEncoder.encode(getCurrentUrl(request),"utf-8");
 
                response.sendRedirect(reLoginUrl);
                returnfalse;
            }
        }
 
        returntrue;
    }
 
    privateString getCurrentUrl(HttpServletRequest request) {
        String currentUrl = request.getRequestURL().toString();
        if(!StringUtils.isEmpty(request.getQueryString())) {
            currentUrl +="?"+ request.getQueryString();
        }
 
        returncurrentUrl;
    }
}

4. [代码]springMVC 配置文件,增加需要进行拦截的url     

?
1
2
3
4
5
6
7
8
<!-- 安全拦截用的 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mappingpath="/forum/post"/>
            <mvc:mappingpath="/forum/reply/*"/>
            <beanclass="com.uncle5.pubrub.web.security.CsrfInterceptor"/>
        </mvc:interceptor>       
    </mvc:interceptors>

5. [代码]jsp页面,需要注意的是必须使用spring的form标签     

?
1
2
3
4
5
6
7
8
9
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
 
<divstyle="margin: 0 auto; border: 1px solid orange; width: 80%; height: 400px;">
        <form:formaction="/forum/post"method="post">
            <span>标题:</span><inputtype="text"name="title"id="title">
            <textareaname="content"id="content"rows="30"cols="40"></textarea>
            <inputtype="submit"name="submit"value="submit">
        </form:form>
    </div>

6. [代码]jsp页面 查看源码会发现已经添加上了hidden字段     

?
1
2
3
4
5
6
7
8
<divstyle="margin: 0 auto; border: 1px solid orange; width: 80%; height: 400px;">
        <formid="command"action="/forum/post"method="post">
            <span>标题:</span><inputtype="text"name="title"id="title">
            <textareaname="content"id="content"rows="30"cols="40"></textarea>          
            <inputtype="submit"name="submit"value="submit">
        <inputtype="hidden"name="CSRFToken"value="35afec82-da7b-449e-9ae9-b38664b5af63"/>
</form>
    </div>

7. [代码]相关原理说明     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1.只有当使用spring的form标签时候,才会在渲染jsp页面时候触发
org.springframework.web.servlet.tags.form.FormTag 类中的
 
@Override
    publicintdoEndTag()throwsJspException {
        RequestDataValueProcessor processor = getRequestContext().getRequestDataValueProcessor();
        ServletRequest request =this.pageContext.getRequest();
        if((processor !=null) && (requestinstanceofHttpServletRequest)) {
            writeHiddenFields(processor.getExtraHiddenFields((HttpServletRequest) request));
        }
        this.tagWriter.endTag();
        returnEVAL_PAGE;
    }
该方法会调用上文中所说的CsrfRequestDataValueProcessor中的创建隐藏域的方法getExtraHiddenFields来创建csrfToken隐藏域。
 
2.对相关需要进行防范csrf攻击的post请求地址进行拦截,此处是依赖springMVC中提供的拦截器机制来操作的
<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/forum/post"/>
            <mvc:mapping path="/forum/reply/*"/>
            <beanclass="com.uncle5.pubrub.web.security.CsrfInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
当用户访问"/forum/post"这个请求时候,会直接进入CsrfInterceptor的preHandle方法,此处针对post请求

本文转载自:http://www.oschina.net/code/snippet_1029551_27153

共有 人打赏支持
java梦想家01
粉丝 11
博文 61
码字总数 14212
作品 0
海淀
对CSRF你了解多少

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它...

FantJ
2017/11/28
0
0
经常被忽视的攻击 —— CSRF (跨站请求伪造)

CSRF(Cross-site request forgery 跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它...

oschina
2012/10/06
5.6K
9
CSRF/XSRF 跨站请求伪造

CSRF(Cross Site Request Forgery, 跨站域请求伪造)也称 XSRF, 是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一。其他安全隐患,比如 SQL 脚本注入,跨站域脚本攻击...

给你添麻烦了
01/13
0
0
电商安全无小事,如何有效地抵御 CSRF 攻击?

现在,我们绝大多数人都会在网上购物买东西。但是很多人都不清楚的是,很多电商网站会存在安全漏洞。比如乌云就通报过,国内很多家公司的网站都存在 CSRF 漏洞。如果某个网站存在这种安全漏洞...

OneAPM蓝海讯通
2015/11/24
42
0
客厅保卫战:央视引爆无线路由器安全话题

出来混总是要还的,为了所谓的用户体验和快速扩张市场,十几年来Wi-Fi设备制造行业向来不太重视安全功能和服务,固件更新周期很长,安全漏洞迟迟得不到修复,而且Wi-Fi技术标准本身的各种缺陷...

CashCat
2014/03/03
0
0
安全|常见的Web攻击手段之CSRF攻击

对于常规的Web攻击手段,如XSS、CRSF、SQL注入、(常规的不包括文件上传漏洞、DDoS攻击)等,防范措施相对来说比较容易,对症下药即可,比如XSS的防范需要转义掉输入的尖括号,防止CRSF攻击需...

小怪聊职场
04/21
0
0
常见web攻击与防御策略

1.XSS 说明: XSS攻击全称 跨站脚本攻击(Cross Site Scripting),是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS. XSS简单分为反射型、存储型(DOM型属...

Separes
2017/12/19
0
0
最牛「CSRF防护」,带你进入大虾们的圈子!

简单理解 CSRF 什么是 CSRF? CSRF,通常称为跨站请求伪造,英文名 Cross-site request forgery 缩写 CSRF,是一种对网站的恶意攻击。一个跨站请求伪造攻击迫使登录用户的浏览器将伪造的HTT...

OneAPM蓝海讯通
2016/01/18
36
0
Web安全的三个攻防姿势

关于前端Web安全的问题,是一个老生常谈的问题,作为离用户最近的一层,我们大前端确实需要把手伸的更远一点。 我们最常见的Web安全攻击有以下几种 XSS 跨站脚本攻击 CSRF 跨站请求伪造 clic...

木羽zwwill
2017/10/18
0
0
CSRF漏洞分析利用及防御

0x00 简要介绍 CSRF(Cross-site request forgery)跨站请求伪造,由于目标站无 token/refer 限制,导致攻击者可以以用户的身份完成操作达到各种目的。根据HTTP请求方式,CSRF利用方式可分为...

nw01f
2016/06/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

shell中的函数、shell中的数组、告警系统需求分析

shell中的函数 格式: 格式: function f_name() { command } 函数必须要放在最前面 示例1(用来打印参数) 示例2(用于定义加法) 示例3(用于显示IP) shell中的数组 shell中的数组1 定义数...

Zhouliang6
今天
2
0
用 Scikit-Learn 和 Pandas 学习线性回归

      对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题     没有...

wangxuwei
今天
1
0
MAC安装MAVEN

一:下载maven压缩包(Zip或tar可选),解压压缩包 二:打开终端输入:vim ~/.bash_profile(如果找不到该文件新建一个:touch ./bash_profile) 三:输入i 四:输入maven环境变量配置 MAVEN_HO...

WALK_MAN
今天
0
0
33.iptables备份与恢复 firewalld的9个zone以及操作 service的操作

10.19 iptables规则备份和恢复 10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作 10.19 iptables规则备份和恢复: ~1. 保存和备份iptables规则 ~2...

王鑫linux
今天
2
0
大数据教程(2.11):keeperalived+nginx高可用集群搭建教程

上一章节博主为大家介绍了目前大型互联网项目的系统架构体系,相信大家应该注意到其中很重要的一块知识nginx技术,在本节博主将为大家分享nginx的相关技术以及配置过程。 一、nginx相关概念 ...

em_aaron
今天
1
0
Apache Directory Studio连接Weblogic内置LDAP

OBIEE默认使用Weblogic内置LDAP管理用户及组。 要整理已存在的用户及组,此前办法是导出安全数据,文本编辑器打开认证文件,使用正则表达式获取用户及组的信息。 后来想到直接用Apache Dire...

wffger
今天
2
0
HFS

FS,它是一种上传文件的软件。 专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,...

garkey
今天
1
0
Java IO类库之BufferedInputStream

一、BufferedInputStream介绍 /** * A <code>BufferedInputStream</code> adds * functionality to another input stream-namely, * the ability to buffer the input and to * sup......

老韭菜
今天
0
0
STM 32 窗口看门狗

http://bbs.elecfans.com/jishu_805708_1_1.html https://blog.csdn.net/a1985831055/article/details/77404131...

whoisliang
昨天
1
0
Dubbo解析(六)-服务调用

当dubbo消费方和提供方都发布和引用完成后,第四步就是消费方调用提供方。 还是以dubbo的DemoService举例 -- 提供方<dubbo:application name="demo-provider"/><dubbo:registry address="z...

青离
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部