Spring Security has enabled CSRF defense by default.
What is CSRF
CSRF is a browser cross site forged request. Hackers can induce users to perform some unexpected behaviors, which allows attackers to partially bypass the homologous strategy.
For example, after the user logs in to system A, the user can modify his mailbox, and then the browser submits the request as follows
POST /email/change HTTP/1.1 Host: vulnerable-website.com Content-Type: application/x-www-form-urlencoded Content-Length: 30 Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE email=wiener@normal-user.com
Then, at this time, the hacker constructs his own web site and constructs a form.
<form action="http://www.test.com/dfasd/email/change" method="post" id="myForm"> <input type="hidden" value="test@normal-user.com" name="email"> <input type="button" value="Point me" id="submitBtn"> </form>
When the user browses the web site B (the user does not log out of system A), clicking A link of the web site B is actually submitting A form request, and then the hacker modifies the user's mailbox. The request is as follows
POST /email/change HTTP/1.1 Host: vulnerable-website.com Content-Type: application/x-www-form-urlencoded Content-Length: 30 Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE email=test@normal-user.com
This is because when you click this link, you will access system A and bring the Cookie information related to system A.
CSRF defense
Spring proposes two ways to defend against CSRF:
- Token synchronization
- Specify the SameSite property on the Cookie.
Token synchronization
The principle of token synchronization is to generate a random string token on the server and save a copy on the server. After the current segment request arrives, compare the token carried by the request with the server. If it is equal, it passes; Or refuse.
SameSite
By specifying the SameSite attribute on the Cookie, the browser is required not to carry Cookie information when sending requests from external sites, so as to prevent CSRF attacks.
There are three SameSite attribute values:
- Strict: only requests sent by the same site contain Cookie requests. Requests sent by different sites will not contain Cookie information.
- Lax: the request sent by the same site or the GET request navigating to the target address automatically contains Cookie information, otherwise it does not contain Cookie information.
- None: cookies will be sent in all contexts, that is, cross domain requests are allowed.
Spring Security CSRF defense source code
CsrfToken
CsrfToken is an interface used to provide token related information. It has two implementation classes:
- SaveOnAccessCsrfToken: when accessing a token, determine whether to store the token.
- DefaultCsrfToken: a simple implementation of the interface
public interface CsrfToken extends Serializable { String getHeaderName(); String getParameterName(); String getToken(); }
CsrfTokenRepository
CsrfTokenRepository is an interface used to store, generate and obtain tokens. Its interface has three default implementations:
- Cookie csrftokenrepository: stores the information of the token in the cookie, which is based on the implementation of the cookie.
- HttpSessionCsrfTokenRepository: stores the token information in Session based on the Session implementation.
- LazyCsrfTokenRepository: This is a proxy class. It is stored only when the token is accessed.
public interface CsrfTokenRepository { CsrfToken generateToken(HttpServletRequest request); void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response); CsrfToken loadToken(HttpServletRequest request); }
Questions not understood
Spring Security enables csrf defense by default, and POST submission will report errors. The default LazyCsrfTokenRepository does not understand the token logic. Here is an alternative solution: configure CookieCsrfTokenRepository to replace LazyCsrfTokenRepository class.
CsrfFilter filter
CsrfFilter filter is used to verify tokens, and throw exceptions for failed tokens. CsrfFilter processing logic: first, load the token information carried in the request through the token repository. If there is no token, a new token is generated and stored in a Cookie or Session (depending on your configuration). Then match the request once (the default is to judge whether the request method is "GET", "HEAD", "TRACE" and "OPTIONS"). If the request method is POST, the token information needs to be verified.
to configure
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
Here is the process of configuring cookies.
Here is a key point: when obtaining a token through the request. Getparameter (parametername) method, you need to know the defined parametername name. If an attacker constructs a form in his own website, he does not know this value. This protects against CSRF attacks.
CsrfAuthenticationStrategy
CsrfAuthenticationStrategy authentication is called when the user logs in successfully. The approximate call chain is abstractauthenticationprocessingfilter - > CsrfAuthenticationStrategy
CsrfAuthenticationStrategy processing logic is as follows:
@Override public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) throws SessionAuthenticationException { boolean containsToken = this.csrfTokenRepository.loadToken(request) != null; if (containsToken) { this.csrfTokenRepository.saveToken(null, request, response); CsrfToken newToken = this.csrfTokenRepository.generateToken(request); this.csrfTokenRepository.saveToken(newToken, request, response); request.setAttribute(CsrfToken.class.getName(), newToken); request.setAttribute(newToken.getParameterName(), newToken); } }
reference resources
remarks
This series is all notes for learning Spring Security in simple terms