使用AngularJS与SpringSecurity3.2的CSRF [英] Using AngularJS with SpringSecurity3.2 for CSRF
问题描述
AngularJS
的index.html
< HEAD>
< META NAME =_ CSRFCONTENT =$ {_ csrf.token}/>
<! - 默认的标题名称为X-CSRF-TOKEN - >
< META NAME =_ csrf_headerCONTENT =$ {_ csrf.headerName}/>
< /头>
SpringSecurity 3.2
Spring使用的 HttpSessionCsrfTokenRepository 在默认情况下为CSRF给出了头名的 X-CSRF-TOKEN ,但是Anuglar约定的 X-XSRF-TOKEN
我想延长 HttpSessionCsrfTokenRepository 并重写头名,但由于它被标记为最终我最终实现自定义标记库。
@Component
公共类CustomCsrfTokenRepository实现CsrfTokenRepository { 公共静态最后弦乐CSRF_PARAMETER_NAME =_csrf; 公共静态最后弦乐CSRF_HEADER_NAME =X-XSRF-TOKEN 私人最终地图<弦乐,CsrfToken> tokenRepository =新的ConcurrentHashMap<>(); 公共CustomCsrfTokenRepository(){
log.info(创建{},CustomCsrfTokenRepository.class.getSimpleName());
} @覆盖
公共CsrfToken的generateToken(HttpServletRequest的请求){
返回新DefaultCsrfToken(CSRF_HEADER_NAME,CSRF_PARAMETER_NAME,createNewToken());
} @覆盖
公共无效saveToken(CsrfToken令牌,HttpServletRequest的请求,HttpServletResponse的响应){
字符串键= getKey(请求);
如果(键== NULL)
返回; 如果(令牌== NULL){
tokenRepository.remove(键);
}其他{
tokenRepository.put(键,令牌);
}
} @覆盖
公共CsrfToken loadToken(HttpServletRequest的请求){
字符串键= getKey(请求);
返回键== NULL?空:tokenRepository.get(键);
} 私有String getKey(HttpServletRequest的请求){
返回request.getHeader(授权);
} 私人字符串createNewToken(){
返回UUID.randomUUID()的toString()。
}
}
SecurityConfig.java
@Configuration
@EnableWebSecurity
公共类SecurityConfig扩展WebSecurityConfigurerAdapter { @注入
私人CustomCsrfTokenRepository customCsrfTokenRepository;
@覆盖
保护无效配置(HttpSecurity HTTP)抛出异常{ HTTP
// .addFilterAfter(新CsrfTokenGeneratorFilter(),CsrfFilter.class)
。异常处理()
.authenticationEntryPoint(的AuthenticationEntryPoint)
。和()
.formLogin()
.loginProcessingUrl(/应用/验证)
.successHandler(ajaxAuthenticationSuccessHandler)
.failureHandler(ajaxAuthenticationFailureHandler)
.usernameParameter(为j_username)
.passwordParameter(为j_password)
.permitAll()
。和() .csrf()
.csrfTokenRepository(customCsrfTokenRepository)
。和()
}
}
-
我怎样才能干净地覆盖头名,而不是创建一个自定义csrfTokenRepository的?
-
有没有我需要的单页做任何其他配置更改
应用程序如AngularJS,因为这还没有工作。
在使用Java配置Spring Security的,下面应该是可能的:
公共无效配置(最终HttpSecurity HTTP)抛出异常
{
最后HttpSessionCsrfTokenRepository tokenRepository =新HttpSessionCsrfTokenRepository();
tokenRepository.setHeaderName(X-XSRF-TOKEN); http.csrf()csrfTokenRepository(tokenRepository)。
}
并发症是单页面应用程序依靠AJAX和包括CSRF与AJAX请求令牌是一个有点复杂。当使用AngularJS,服务器应在第一次请求,只要发送称为会话cookie XSRF-TOKEN
用户登录或注销。那么AngularJS将返回HTTP头这个cookie的值 X-XSRF-TOKEN
所有的请求,让服务器可以检查。
AngularJS
index.html
<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
</head>
SpringSecurity 3.2
Spring uses HttpSessionCsrfTokenRepository which by default gives header name for CSRF as X-CSRF-TOKEN, however Anuglar convention is X-XSRF-TOKEN
I wanted to extend HttpSessionCsrfTokenRepository and override the header name, but since it is marked final I ended up implementing a custom token repository.
@Component
public class CustomCsrfTokenRepository implements CsrfTokenRepository {
public static final String CSRF_PARAMETER_NAME = "_csrf";
public static final String CSRF_HEADER_NAME = "X-XSRF-TOKEN";
private final Map<String, CsrfToken> tokenRepository = new ConcurrentHashMap<>();
public CustomCsrfTokenRepository() {
log.info("Creating {}", CustomCsrfTokenRepository.class.getSimpleName());
}
@Override
public CsrfToken generateToken(HttpServletRequest request) {
return new DefaultCsrfToken(CSRF_HEADER_NAME, CSRF_PARAMETER_NAME, createNewToken());
}
@Override
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
String key = getKey(request);
if (key == null)
return;
if (token == null) {
tokenRepository.remove(key);
} else {
tokenRepository.put(key, token);
}
}
@Override
public CsrfToken loadToken(HttpServletRequest request) {
String key = getKey(request);
return key == null ? null : tokenRepository.get(key);
}
private String getKey(HttpServletRequest request) {
return request.getHeader("Authorization");
}
private String createNewToken() {
return UUID.randomUUID().toString();
}
}
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Inject
private CustomCsrfTokenRepository customCsrfTokenRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// .addFilterAfter(new CsrfTokenGeneratorFilter(), CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.formLogin()
.loginProcessingUrl("/app/authentication")
.successHandler(ajaxAuthenticationSuccessHandler)
.failureHandler(ajaxAuthenticationFailureHandler)
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll()
.and()
.csrf()
.csrfTokenRepository(customCsrfTokenRepository)
.and()
}
}
How can I cleanly override the header name instead of creating a custom csrfTokenRepository?
Is there any other configuration changes I need to do for Single Page Applications such as AngularJS, as this does not work yet.
When using Java configuration for Spring Security, the following should be possible:
public void configure(final HttpSecurity http) throws Exception
{
final HttpSessionCsrfTokenRepository tokenRepository = new HttpSessionCsrfTokenRepository();
tokenRepository.setHeaderName("X-XSRF-TOKEN");
http.csrf().csrfTokenRepository(tokenRepository);
}
The complication is that single-page applications rely on AJAX and including CSRF tokens with AJAX requests is a bit complicated. When using AngularJS, the server should send a session cookie called XSRF-TOKEN
upon first request and whenever a user logs in or logs out. AngularJS will then return the value of this cookie in the HTTP header X-XSRF-TOKEN
with all requests, which the server can then check.
这篇关于使用AngularJS与SpringSecurity3.2的CSRF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!