小组Java

最近在做的一个spring boot的web项目(前后端分离的实现方式)刚好用到了spring security方面的框架,在实践过程中有不少的经验总结, 所以mark一下,以后留用。

spring security在集成spring boot的微服务框架后,实现了cas认证和权限控制,这方面在网上也有颇多的资料介绍,这里不细说,这里 主要介绍的是spring security关于csrf方面的实现细节。

科普一下,什么是csrf,这是一个web应用安全的问题,CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack” 或者Session Riding,我们知道,客户端与服务端在基于http协议在交互的数据的时候,由于http协议本身是无状态协议,后来引进了cookie的 方式进行记录服务端和客户端的之间交互的状态和标记。cookie里面一般会放置服务端生成的session id(会话ID)用来识别客户端访问服务端过 程中的客户端的身份标记。在跨域(科普一下:同一个ip、同一个网络协议、同一个端口,三者都满足就是同一个域,否则就有跨域问题)的情况下, session id可能会被恶意第三方劫持,此时劫持这个session id的第三方会根据这个session id向服务器发起请求,此时服务器收到这个请求会 认为这是合法的请求,并返回根据请求完成相应的服务端更新。比较关键的一点是,如果这个http请求是get方式发起的请求,意味着它只是访问服务器 的资源,仅仅只是查询,没有更新服务器的资源,所以对于这类请求,spring security的防御策略是允许的,如果这个请求是通过post请求发起的, 那么spring security是默认拦截这类请求的,因为这类请求是带有更新服务器资源的危险操作,如果恶意第三方可以通过劫持session id来更新 服务器资源,那会造成服务器数据被非法的篡改,所以这类请求是会被Spring security拦截的,在默认的情况下,spring security是启用csrf 拦截功能的,这会造成,在跨域的情况下,post方式提交的请求都会被拦截无法被处理(包括合理的post请求),前端发起的post请求后端无法正常 处理,虽然保证了跨域的安全性,但影响了正常的使用,如果关闭csrf防护功能,虽然可以正常处理post请求,但是无法防范通过劫持session id的非法的post请求,所以spring security为了正确的区别合法的post请求,采用了token的机制。

在跨域的场景下,客户端访问服务端会首先发起get请求,这个get请求在到达服务端的时候,服务端的Spring security会有一个过滤 器 CsrfFilter去检查这个请求,如果这个request请求的http header里面的X-CSRF-COOKIE的token值为空的时候,服务端就好自动生成一个 token值放进这个X-CSRF-COOKIE值里面,客户端在get请求的header里面获取到这个值,如果客户端有表单提交的post请求,则要求客户端要 携带这个token值给服务端,在post请求的header里面设置_csrf属性的token值,提交的方式可以是ajax也可以是放在form里面设置hidden 属性的标签里面提交给服务端,服务端就会根据post请求里面携带的token值进行校验,如果跟服务端发送给合法客户端的token值是一样的,那么 这个post请求就可以受理和处理,如果不一样或者为空,就会被拦截。由于恶意第三方可以劫持session id,而很难获取token值,所以起到了 安全的防护作用。

在设置spring security的时候,要设置服务端是支持跨域的,通常是通过声明一个支持跨域的的过滤器来支持跨域访问的。

然后在前端也要做一下跨域的设置

在服务端spring security的配置类里面SecurityConfig类里面可以设置一下token的生成方式

如果想详细了解CsrfFilter的实现原理,建议看一下CsrfFilter的源码,通过debug方式打断点进去看,只是了解基本原理,看本文即可。 本文纯手打,讲解的过程中可能存在一些瑕疵,希望高手路过的时候可以指正,本人将会及时更新博客来修正错误。

如果在讲述原理有不明白的地方可以在博客下面留言,我看到了就会及时的回复,互相的交流进步,分享是一种美德。

5 3 收藏


直接登录
最新评论
  • 光光头去打酱油 全干工程师(公司打杂的) 2016/09/19

     

  • 咋看不到代码呀

  • 正在学习security,就是一个简单的页面跳转,从login.jsp跳到index.jsp,满足同一个ip、同一个http协议、同一个端口号,当从login.jsp点击登录后,依然报“Could not verify the provided CSRF token because your session was not found.”查了半天资料一点头绪都没有,请求楼主帮助!我的核心配置如下(使用的是security4.2)

    <security:http auto-config=”true”>
    <security:form-login  login-page=”/login.jsp”/>
    <security:intercept-url pattern=”/login.jsp*” access=”permitAll”/>
    <security:intercept-url pattern=”/admin.jsp*” access=”hasRole(‘ROLE_ADMIN’)”/>
    <security:intercept-url pattern=”/**” access=”hasRole(‘ROLE_USER’)” />
    </security:http>

    <security:authentication-manager>
    <security:authentication-provider>
    <security:password-encoder hash=”md5″/>
    <!–
    <security:user-service>
    <security:user name=”user” password=”user”
    authorities=”ROLE_USER” />
    </security:user-service>
    –>
    <security:jdbc-user-service data-source-ref=”dataSourceMeta”/>
    </security:authentication-provider>

    </security:authentication-manager>

    login.jsp为

    <%@ page language=”java” pageEncoding=”UTF-8″%>
    <html>
    <head>
    <title>用户登录</title>
    </head>
    <body>
    <h3>用户登录</h3>
    <form action=”${pageContext.request.contextPath}/j_spring_security_check” method=”post”>

    用户名:<input type=”text” name=”j_username”/><br/>
    密    码:<input type=”password” name=”j_password”/><br/>

    <input type=”submit” value=”登录”/>

    </form>
    </body>
    </html>

     

    index.jsp为

    <%@ page language=”java” pageEncoding=”UTF-8″%>
    <html>
    <head>
    <title>首页</title>
    </head>
    <body>
    这是首页。欢迎您!<br/>
    <a href=”admin.jsp”>进入admin.jsp页面</a>
    </body>
    </html>

     

  • 怎么配置是空的