在spring控制器中获取_csrf
Posted
技术标签:
【中文标题】在spring控制器中获取_csrf【英文标题】:Get _csrf in spring controller 【发布时间】:2016-07-20 06:28:43 【问题描述】:如何在 spring 控制器中获取 _csrf 对象(?!)?我已经配置了 Spring Security 并且可以在 jsp 文件中获取 $_csrf 请求属性。 我试过了:
CsrfToken _csrf = (CsrfToken) session.getAttribute("CsrfToken");
CsrfToken _csrf = (CsrfToken) session.getAttribute("_csrf");
结果为空;
提前致谢!
【问题讨论】:
【参考方案1】:在调试中,我看到了一个带有键“org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN”的会话属性。我查看了HttpSessionCsrfTokenRepository 课程。它有一个从传入的 HttpServletRequest 对象加载令牌的方法。
最后这对我有用:
CsrfToken token = new HttpSessionCsrfTokenRepository().loadToken(request);
如果有人向我解释这是如何工作的,我将不胜感激。
【讨论】:
您基本上是从来自 AJAX 的服务器请求标头中提取令牌。如果要获取headerName
、getParameterName
和token
,可以分别使用CsrfToken token = new HttpSessionCsrfTokenRepository().loadToken(request).getHeaderName();
、CsrfToken token = new HttpSessionCsrfTokenRepository().loadToken(request).getParameterName();
和CsrfToken token = new HttpSessionCsrfTokenRepository().loadToken(request).getToken();
获取。【参考方案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
【讨论】:
【参考方案3】:试试:
CsrfToken token = (CsrfToken) session.getAttribute(CsrfToken.class.getName());
【讨论】:
感谢@NikolaB 的回复。但它给出了null。在调试中,我看到一个带有键“org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN”的会话属性。 什么是“会话”变量?您如何获得对它的引用? 你应该可以在控制器中注入它(Spring会管理这个):@Autowired private HttpSession session;【参考方案4】:我认为在您之前的尝试中,您将 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名,第三个是存放在session中的key。 loadToken
方法实际上并没有从请求对象中获取令牌 - 它从请求中获取会话对象,然后查找令牌,该令牌之前使用由 sessionAttributeName
定义的键存储。
【讨论】:
【参考方案5】:如果您想直接从session
获取它,这也有效
CsrfToken token = (CsrfToken) session.getAttribute("org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN");
【讨论】:
【参考方案6】:您可以在 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();
-
启用 csrf 并使用
CookieCsrfTokenRepository
csrf 令牌存储库。
从带有 cookie 名称的 cookie 中获取令牌 - “XSRF-TOKEN”
在另一个请求中使用此令牌 [GET、HEAD、TRACE、OPTIONS 除外] 标头,标头键为 X-XSRF-TOKEN
【讨论】:
以上是关于在spring控制器中获取_csrf的主要内容,如果未能解决你的问题,请参考以下文章
如何在spring mvc控制器中获取getServletContext()