简体   繁体   中英

How can Spring add a new _csrf token to a session variable?

When someone does a POST to /oauth/authorize in Spring OAuth2 ( Source code for the API at this link ), the CSRF token is updated at the server.

What specific code syntax can be used to:
1.) Access the newly minted CSRF token in code?
2.) Assign a copy of the newly minted CSRF token to an inert session variable?
3.) Subsequently retrieve the new session variable for use in a different class?

The context for this requirement is a control flow that involves variable routing through multiple filters and controllers while a user makes a number of passes through the /oauth/authorize endpoint. Variables need to be saved to session scope and then retrieved from session scope and placed back into request scope, as needed by an algorithm.

Examples of the types of classes that might need to create and consume the above described session variables include:

1.) any class with an @Controller annotation ,
2.) any custom implementation of OncePerRequestFilter ,
3.) any custom implementation of DefaultOAuth2RequestFactory ,
4.) and other types of classes employed in custom filter chains.

This might be a Spring MVC question or a Spring Security question, or both, even though it involves the Spring OAuth2 API, whose source code is built up from Spring MVC and Spring Security.

The Spring Security documentation covers this in detail. You can access the token using the section title Include the CSRF Token . A summary from this section:

  • One way to approach this is to use the _csrf request attribute to obtain the current CsrfToken . An example of doing this with a JSP is shown below:
<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}"
    method="post">
<input type="submit"
    value="Log out" />
<input type="hidden"
    name="${_csrf.parameterName}"
    value="${_csrf.token}"/>
</form>
  • If you are using Spring MVC <form:form> tag or Thymeleaf 2.1+ and are using @EnableWebSecurity , the CsrfToken is automatically included for you (using the CsrfRequestDataValueProcessor ). See Automatic Token Inclusion for details.
  • Spring Security provides CsrfTokenResolver which can automatically resolve the current CsrfToken for Spring MVC arguments. By using @EnableWebSecurity you will automatically have this added to your Spring MVC configuration. If you use XML based configuraiton, you must add this yourself.

Once CsrfTokenResolver is properly configured, you can expose the CsrfToken to your static HTML based application.

@RestController
public class CsrfController {

    @RequestMapping("/csrf")
    public CsrfToken csrf(CsrfToken token) {
        return token;
    }
}

It is important to keep the CsrfToken a secret from other domains. This means if you are using Cross Origin Sharing (CORS), you should NOT expose the CsrfToken to any external domains.

This is what the OP was asking for:

1.) Retrieve a CSRF token as follows:

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
CsrfToken csrf = (CsrfToken) attr.getRequest().getAttribute(CsrfToken.class.getName());

2.) Then do whatever you want with the token. (Tread lightly and know what you are doing so that you do not make a mess.) Perhaps put the csrf token into an inert session variable in one class' code and leave it there until it needs to be pulled out in a different class' code.

3.) Then (probably in a different class' code elsewhere in the control flow) put the token back into the request as follows:

attr.setAttribute("_csrf", csrf, RequestAttributes.SCOPE_REQUEST);
RequestContextHolder.setRequestAttributes(attr);

The above would be used to clean up side effects of custom processing. For example, a situation in which an old request is saved and then re-used in a custom implementation of DefaultOAuth2RequestFactory or OncePerRequestFilter , but the csrf token value changed between the time of the old request's creation and the new request, so that the csrf value needs to be updated in the old request before it can be added into the control flow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM