在 spring 控制器中获取 _csrf
Get _csrf in spring controller
如何在 spring 控制器中获取 _csrf 对象 (?!)?我已经配置了 Spring 安全并且可以在 jsp 文件中获取 ${_csrf} 请求属性。
我试过:
CsrfToken _csrf = (CsrfToken) session.getAttribute("CsrfToken");
CsrfToken _csrf = (CsrfToken) session.getAttribute("_csrf");
结果为空;
提前致谢!
尝试:
CsrfToken token = (CsrfToken) session.getAttribute(CsrfToken.class.getName());
在调试中,我看到一个带有键 "org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN" 的会话属性。我查看了 HttpSessionCsrfTokenRepository class。它有一个从传入的 HttpServletRequest 对象加载令牌的方法。
最后这对我有用:
CsrfToken token = new HttpSessionCsrfTokenRepository().loadToken(request);
如果有人向我解释这是如何工作的,我将不胜感激。
我认为在您之前的尝试中,您混淆了 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;
第一个是token作为POST参数出现时的参数名,第二个是请求头中出现时的header名,第三个是存放它的key在会话中。 loadToken
方法实际上并没有从请求对象中获取令牌 - 它从请求中获取会话对象,然后查找令牌,该令牌先前使用 sessionAttributeName
定义的密钥存储。
如果您想直接从 session
获取它,这也适用
CsrfToken token = (CsrfToken) session.getAttribute("org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN");
要在 Spring 控制器中访问 CSRF 令牌,您只需这样做:
@Controller
public class FooController {
@RequestMapping("/foo")
public void foo(CsrfToken token) {
// Do whatever with token
}
}
Spring 将根据参数类型自动检测到您需要的令牌,并将其注入到您的方法中。
这至少从 Spring Security 5.0 起有效,如果您使用 Spring 引导或在您的配置中有 @EnableWebSecurity
注释。
您可以在 Controller 的资源方法中将 HttpServletRequest
实例作为参数。使用此请求 object 您可以轻松获得 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
class创建的Csrf Token值,如下:-
UUID.randomUUID().toString();
检查 org.springframework.security.web.csrf.CookieCsrfTokenRepository
和 org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository
classes,它们是 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();
}
}
- 启用 csrf 并使用
CookieCsrfTokenRepository
csrf 令牌存储库。
- 使用 cookie 名称从 cookie 中获取令牌 -“XSRF-TOKEN”
- 在其他请求中使用此令牌 [GET、HEAD、TRACE、OPTIONS 除外] header 以 header 键作为
X-XSRF-TOKEN
如何在 spring 控制器中获取 _csrf 对象 (?!)?我已经配置了 Spring 安全并且可以在 jsp 文件中获取 ${_csrf} 请求属性。 我试过:
CsrfToken _csrf = (CsrfToken) session.getAttribute("CsrfToken");
CsrfToken _csrf = (CsrfToken) session.getAttribute("_csrf");
结果为空;
提前致谢!
尝试:
CsrfToken token = (CsrfToken) session.getAttribute(CsrfToken.class.getName());
在调试中,我看到一个带有键 "org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN" 的会话属性。我查看了 HttpSessionCsrfTokenRepository class。它有一个从传入的 HttpServletRequest 对象加载令牌的方法。
最后这对我有用:
CsrfToken token = new HttpSessionCsrfTokenRepository().loadToken(request);
如果有人向我解释这是如何工作的,我将不胜感激。
我认为在您之前的尝试中,您混淆了 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;
第一个是token作为POST参数出现时的参数名,第二个是请求头中出现时的header名,第三个是存放它的key在会话中。 loadToken
方法实际上并没有从请求对象中获取令牌 - 它从请求中获取会话对象,然后查找令牌,该令牌先前使用 sessionAttributeName
定义的密钥存储。
如果您想直接从 session
CsrfToken token = (CsrfToken) session.getAttribute("org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN");
要在 Spring 控制器中访问 CSRF 令牌,您只需这样做:
@Controller
public class FooController {
@RequestMapping("/foo")
public void foo(CsrfToken token) {
// Do whatever with token
}
}
Spring 将根据参数类型自动检测到您需要的令牌,并将其注入到您的方法中。
这至少从 Spring Security 5.0 起有效,如果您使用 Spring 引导或在您的配置中有 @EnableWebSecurity
注释。
您可以在 Controller 的资源方法中将 HttpServletRequest
实例作为参数。使用此请求 object 您可以轻松获得 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
class创建的Csrf Token值,如下:-
UUID.randomUUID().toString();
检查 org.springframework.security.web.csrf.CookieCsrfTokenRepository
和 org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository
classes,它们是 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();
}
}
- 启用 csrf 并使用
CookieCsrfTokenRepository
csrf 令牌存储库。 - 使用 cookie 名称从 cookie 中获取令牌 -“XSRF-TOKEN”
- 在其他请求中使用此令牌 [GET、HEAD、TRACE、OPTIONS 除外] header 以 header 键作为
X-XSRF-TOKEN