在spring controller中获取_csrf

时间:2016-03-31 17:06:31

标签: java spring spring-mvc spring-security csrf

如何在弹簧控制器中获取_csrf对象(?!)?我已经配置了Spring Security,并且可以在jsp文件中获得$ {_ csrf}请求属性。 我试过了:

CsrfToken _csrf = (CsrfToken) session.getAttribute("CsrfToken");
CsrfToken _csrf = (CsrfToken) session.getAttribute("_csrf");

结果为null;

提前致谢!

6 个答案:

答案 0 :(得分:4)

在调试中,我看到了一个带有键" org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"的会话属性。我查看了HttpSessionCsrfTokenRepository课程。它有一个从传入的HttpServletRequest对象加​​载令牌的方法。

最后这对我有用:

CsrfToken token = new HttpSessionCsrfTokenRepository().loadToken(request);

如果有人解释我这是如何运作的,我将不胜感激。

答案 1 :(得分:2)

要在Spring控制器中访问CSRF令牌,您只需执行以下操作:

@Controller
public class FooController {
    @RequestMapping("/foo")
    public void foo(CsrfToken token) {
        // Do whatever with token
    }
}

Spring会根据参数的类型自动检测您是否需要令牌,并将其注入您的方法中。

至少从Spring Security 5.0开始,并且如果您使用的是Spring Boot或在配置中带有@EnableWebSecurity批注,则此方法有效。

Documentation

答案 2 :(得分:1)

尝试:

CsrfToken token = (CsrfToken) session.getAttribute(CsrfToken.class.getName());

答案 3 :(得分:1)

您可以在 Controller 的资源方法中使用 HttpServletRequest 实例作为参数。使用此请求对象,您可以轻松获取 csrf 令牌。

@Controller
@RequestMapping("/api/v1/test")
public class TestController {
   
  @GetMapping
  public String test(HttpServletRequest request) {
    CsrfToken csrfToken = 
           (CsrfToken)httpServletRequest.getAttribute(CsrfToken.class.getName());
    if(csrfToken != null)
      return csrfToken.getToken();
    return "Token Not Found";
  }

}

使用 java.util.UUID 类创建的 Csrf Token 值,如下:-

UUID.randomUUID().toString();

检查 org.springframework.security.web.csrf.CookieCsrfTokenRepositoryorg.springframework.security.web.csrf.HttpSessionCsrfTokenRepository 类,它们是 CsrfTokenRepository 内的 spring-security-web-X.X.X.RELEASE.jar 实现。

如果你想在客户端(比如浏览器)有响应的 cookie 中的 CSRF 令牌,那么:-

    @Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {

   http
     .csrf()
     .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
     .and()
     .....
     .forLogin();
   }
}
  1. 启用 csrf 并使用 CookieCsrfTokenRepository csrf 令牌存储库。
  2. 使用 cookie 名称从 cookie 中获取令牌 - “XSRF-TOKEN”
  3. 在另一个请求 [GET、HEAD、TRACE、OPTIONS 除外] 标头中使用此令牌,标头键为 X-XSRF-TOKEN

答案 4 :(得分:0)

我认为在您之前的尝试中,您将CSRF参数名称与会话属性名称混合在一起,并尝试CsrfToken.class.getName(),这些HttpSessionCsrfTokenRepository可能在早期版本中使用过,也可能未在早期版本中使用过。简单地说,你有正确的想法,但错误的关键。 如果您查看private String parameterName = DEFAULT_CSRF_PARAMETER_NAME; private String headerName = DEFAULT_CSRF_HEADER_NAME; private String sessionAttributeName = DEFAULT_CSRF_TOKEN_ATTR_NAME; 的源代码,您会看到它定义了以下默认值:

loadToken

第一个是令牌作为POST参数时的参数名称,第二个是请求头中的头名称,第三个是将其存储在会话中的键。方法sessionAttributeName实际上并不从请求对象获取令牌 - 它从请求中获取会话对象,然后查找令牌,该令牌先前使用LinkedList::head定义的密钥存储。 / p>

答案 5 :(得分:0)

如果您想直接从session那里获得它,也可以使用

CsrfToken token = (CsrfToken) session.getAttribute("org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN");