如何在弹簧控制器中获取_csrf对象(?!)?我已经配置了Spring Security,并且可以在jsp文件中获得$ {_ csrf}请求属性。 我试过了:
CsrfToken _csrf = (CsrfToken) session.getAttribute("CsrfToken");
CsrfToken _csrf = (CsrfToken) session.getAttribute("_csrf");
结果为null;
提前致谢!
答案 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
批注,则此方法有效。
答案 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.CookieCsrfTokenRepository
和 org.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();
}
}
CookieCsrfTokenRepository
csrf 令牌存储库。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");