一、Springboot安全之防CSRF攻击

(一)简要介绍
  跨站请求伪造(Cross-site request fogery),也被称为one-click attack或者session riding,通常缩写为CSRF或者XSRF,是一种挟制用户在当前已登录的WEB应用程序上执行非本意的操作的攻击方法。

  举个栗子:

  • 用户小z登录了网站A,同时打开网站B
  • 网站B隐蔽的发送一个请求至网站A
  • 网站A通过session、cookie等身份标记判断是用户小z,执行对应操作

  这样网站B内的非法代码就盗用了用户小z的身份,在小z不知情的情况下执行了攻击者需要的操作,这就是跨站请求伪造。

(二)术语解释:

CSRF Token
  服务端为客户端生成令牌,这个令牌将用于请求合法性校验,一般通过请求头或请求参数传递到服务端。

CSRF Token仓库
  服务端组件,用于从请求加载或生成CSRF Token。Spring Security提供了Cookie和HttpSession两种实现。

CSRF请求校验匹配器
  服务端组件,用于判断请求是否需要CSRF校验。

(三)防止攻击逻辑

  • 利用CSRF Token仓库将Http请求获取CSRF Token(该过程可以理解为Web服务端针对当前请求获取CSRF Token)。
  • 通过CSRF Token校验请求匹配器来判断当前请求是否需要CSRF Token校验,若需要,执行下一步;否则,跳过校验。
  • 先从请求头中获取CSRF Token值,若不存在,再从请求参数中获取。(该过程可以理解为获取Web客户端请求中的CSRF Token):
      若均未获取到,将会转向错误页面,并且相应头状态码为:403;
      若CSRF Token值获取到,执行下一步。
  • 将第1步CSRF Token仓库获取的CSRF Token与客户端请求中的CSRF Token进行比较:
       若两值相同,校验通过;
       若不相同,校验失败,将会转向错误页面,并且相应状态码为:403。

(四)CSRF Token仓库
  接口:org.springframework.security.web.csrf.CsrfTokenRepository

Cookie类型(默认)
  实现类:org.springframework.security.web.csrf.CookieCsrfTokenRepository
  CSRF Token存储:客户端,Web浏览器Cookie
  有效时间:Web浏览器会话期间
  特别注意:Cookie方式安全系数相对较低

HttpSession类型
  实现类:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository
  CSRF Token存储:服务端,HttpSession(Servlet容器)
  有效时间:HttpSession 最大不活动时间间隔(#setMaxInactiveInterval(int) )
  特别注意:Servlet 容器需要支持HttpSession复制(分布式HttpSession)

(五)案例演示
添加依赖:


			org.springframework.boot
			spring-boot-starter-security
		

1、创建login.html页面




    
    登录页面



2、创建Web 安全配置类

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().csrfTokenRepository(new CookieCsrfTokenRepository())
                .requireCsrfProtectionMatcher(
                        /**
                         * 拦截“/login”开头的访问路径,不让访问
                         * 拦截所有“POST”请求,不让访问
                         */
//                        httpServletRequest -> httpServletRequest.getRequestURI().startsWith("/login")
//                                && httpServletRequest.getMethod().equals("POST")
                        httpServletRequest -> httpServletRequest.getMethod().equals("POST")
                );
    }
}

3、创建Controller

@Controller
public class SecurityController {
    @GetMapping("/login")
    public String login(){
        return "login";
    }
    @GetMapping("/index")
    public String index(){
        return "index";
    }
}

4、案例演示效果
  在我们提交表单的时候,由于请求方法时"POST",所以该请求会被拦截住!

你可能感兴趣的:(网站安全之攻防篇)