概述
介绍
HttpSessionCsrfTokenRepository
是一个基于HttpSession
保存csrf token
的存储库实现。它具有如下能力:
saveToken
保存csrf token
到http session
loadToken
从http session
中提取csrf token
generateToken
生成csrf token
,值为一个随机UUID
继承关系
使用
public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractHttpConfigurer<CsrfConfigurer<H>, H> {
private CsrfTokenRepository csrfTokenRepository = new LazyCsrfTokenRepository(
new HttpSessionCsrfTokenRepository());
// ...
}
源代码
源代码版本 Spring Security Web 5.1.4.RELEASE
package org.springframework.security.web.csrf;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.util.Assert;
/**
* A CsrfTokenRepository that stores the CsrfToken in the HttpSession.
*
* @author Rob Winch
* @since 3.2
*/
public final class HttpSessionCsrfTokenRepository implements CsrfTokenRepository {
private static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf";
private static final String DEFAULT_CSRF_HEADER_NAME = "X-CSRF-TOKEN";
private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME =
HttpSessionCsrfTokenRepository.class
.getName().concat(".CSRF_TOKEN");
// 将 csrf token 保存在请求参数中时,使用的参数名称
private String parameterName = DEFAULT_CSRF_PARAMETER_NAME;
// 将 csrf token 保存在HTTP头部时,使用的头部名称
private String headerName = DEFAULT_CSRF_HEADER_NAME;
// 将 csrf token 保存在 http session 中时使用的属性名称
private String sessionAttributeName = DEFAULT_CSRF_TOKEN_ATTR_NAME;
// 保存 csrf token 到当前请求对应的 http session 中
public void saveToken(CsrfToken token, HttpServletRequest request,
HttpServletResponse response) {
if (token == null) {
// 如果将要保存的 csrf token 为 null,则获取当前 session,清除其中的
// csrf token 属性
HttpSession session = request.getSession(false);
if (session != null) {
session.removeAttribute(this.sessionAttributeName);
}
}
else {
// 如果将要保存的 csrf token 不为 null, 则获取将当前 session,将
// csrf token 保存到其中
HttpSession session = request.getSession();
session.setAttribute(this.sessionAttributeName, token);
}
}
// 从当前 http session 中获取所保存的 csrf token
public CsrfToken loadToken(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return null;
}
return (CsrfToken) session.getAttribute(this.sessionAttributeName);
}
// 针对当前请求生成一个 csrf token 对象 CsrfToken, 实现类使用 DefaultCsrfToken,
// 这里设置了该 CsrfToken 在头部中保存时的名称为 this.headerName, 在参数中保存时
// 的名称为 this.parameterName,csrf token 的值为一个随机 UUID 的字符串值
public CsrfToken generateToken(HttpServletRequest request) {
return new DefaultCsrfToken(this.headerName, this.parameterName,
createNewToken());
}
/**
* Sets the HttpServletRequest parameter name that the CsrfToken is
* expected to appear on
* @param parameterName the new parameter name to use
*/
public void setParameterName(String parameterName) {
Assert.hasLength(parameterName, "parameterName cannot be null or empty");
this.parameterName = parameterName;
}
/**
* Sets the header name that the CsrfToken is expected to appear on and the
* header that the response will contain the CsrfToken.
*
* @param headerName the new header name to use
*/
public void setHeaderName(String headerName) {
Assert.hasLength(headerName, "headerName cannot be null or empty");
this.headerName = headerName;
}
/**
* Sets the HttpSession attribute name that the CsrfToken is stored in
* @param sessionAttributeName the new attribute name to use
*/
public void setSessionAttributeName(String sessionAttributeName) {
Assert.hasLength(sessionAttributeName,
"sessionAttributename cannot be null or empty");
this.sessionAttributeName = sessionAttributeName;
}
// 产生一个 csrf token 的值,其实是一个随机 UUID 的字符串形式
private String createNewToken() {
return UUID.randomUUID().toString();
}
}