Spring 安全 cookie Angular 仅在第一个被禁止的请求后到达
Spring Security cookie arrives Angular only after first forbidden request
我正在使用 Spring 安全性来保护我的 Spring 数据 REST web 应用程序与 AngularJS。
我的 SecurityConfig 声明如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().and()
.authorizeRequests()
// public ressources
.antMatchers("/index.html", "/templates/public/**", "/js/**", "/").permitAll()
.antMatchers(HttpMethod.GET, "/api/security/user").permitAll()
.antMatchers("/api/**").hasAnyRole("ADMIN", "NORMALUSER")
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(basicAuthenticationEntryPointHandler)
.and().logout().logoutUrl("/logout").logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()).deleteCookies("JSESSIONID").permitAll().and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
我通常遵循 this link 来实现我的目标。
现在,如果我自己第一次登录,angular-请求 $cookies.get("XSRF-TOKEN")
returns undefined 和每个请求我的数据库未被阻止。
但是在注销并再次登录后,它 returns 我的 cookie 和每个数据库请求都被允许。
而且这种情况只会在第二次登录时发生,所以:
未定义
cookie
未定义
cookie
未定义
...
所以现在我希望有人可以在不深入我的结构的情况下帮助我,但如果需要,我会这样做。
提前致谢。
编辑 1: 以下是要求:
关于流程:我正在将令牌记录到我的 CokieCsrfTokenRepository().loadToken() 中,并且显示了所有令牌..
编辑 2: 我的 Angular 服务,我每次登录都会调用它:
function authenticationService($rootScope, $http, $location, $filter, $cookies){
function authenticate(credentials, callback) {
var headers = credentials ? {authorization : "Basic "
+ btoa(credentials.username + ":" + credentials.password)
} : {};
$http.get('api/security/user', {headers : headers}).success(function(data, status, get, header) {
if (data.name) {
$rootScope.authenticated = true;
$rootScope.session = data;
console.log($cookies.get("XSRF-TOKEN")) // -> returns every second login cookie
} else {
$rootScope.authenticated = false;
$rootScope.session = null;
}
console.log($rootScope.session)
callback && callback();
}).error(function() {
$rootScope.authenticated = false;
callback && callback();
});
}
return {
authenticate: function(credentials){
authenticate(credentials, function() {
if ($rootScope.authenticated == true) {
$rootScope.authenticationError = false;
if ($rootScope.session.principal.admin == true){
$location.path("/admin/manage");
} else{
$location.path("/user");
}
} else {
$rootScope.authenticationError = true;
$location.path("/login");
}
});
},
// called by refreshing browser
checkLoggedIn: function(){
authenticate();
},
logout: function(){
$http.post('/logout', {})["finally"](function() {
$rootScope.authenticated = false;
$rootScope.session = null;
$location.path("/login");
});
}
};
}
编辑 3: 我现在提到,如果未定义 cookie,this link 中的方法 loadToken() 仅在记录后调用退出并刷新浏览器(首次登录)。然后显示令牌,我再次登录。但在每一次尝试之后它仍然很好用..
编辑 4: 所以我没有意识到,在第一个被禁止的 POST-请求(在 Edit3 中是 /logout)之后,令牌到达了我的模板。刷新浏览器后,我的所有请求都被允许,因为现在每个请求都会发送 cookie。但是如何解决这个问题?
我的解决方案:
//WebSecurityConfigurerAdapter:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
....
.addFilterAfter(new CsrfCustomFilter(), CsrfFilter.class).and()
.csrf().csrfTokenRepository(csrfTokenRepository());
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
public class CsrfCustomFilter extends OncePerRequestFilter{
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
}
我正在使用 Spring 安全性来保护我的 Spring 数据 REST web 应用程序与 AngularJS。
我的 SecurityConfig 声明如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().and()
.authorizeRequests()
// public ressources
.antMatchers("/index.html", "/templates/public/**", "/js/**", "/").permitAll()
.antMatchers(HttpMethod.GET, "/api/security/user").permitAll()
.antMatchers("/api/**").hasAnyRole("ADMIN", "NORMALUSER")
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(basicAuthenticationEntryPointHandler)
.and().logout().logoutUrl("/logout").logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()).deleteCookies("JSESSIONID").permitAll().and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
我通常遵循 this link 来实现我的目标。
现在,如果我自己第一次登录,angular-请求 $cookies.get("XSRF-TOKEN")
returns undefined 和每个请求我的数据库未被阻止。
但是在注销并再次登录后,它 returns 我的 cookie 和每个数据库请求都被允许。
而且这种情况只会在第二次登录时发生,所以:
未定义
cookie
未定义
cookie
未定义
...
所以现在我希望有人可以在不深入我的结构的情况下帮助我,但如果需要,我会这样做。
提前致谢。
编辑 1: 以下是要求:
关于流程:我正在将令牌记录到我的 CokieCsrfTokenRepository().loadToken() 中,并且显示了所有令牌..
编辑 2: 我的 Angular 服务,我每次登录都会调用它:
function authenticationService($rootScope, $http, $location, $filter, $cookies){
function authenticate(credentials, callback) {
var headers = credentials ? {authorization : "Basic "
+ btoa(credentials.username + ":" + credentials.password)
} : {};
$http.get('api/security/user', {headers : headers}).success(function(data, status, get, header) {
if (data.name) {
$rootScope.authenticated = true;
$rootScope.session = data;
console.log($cookies.get("XSRF-TOKEN")) // -> returns every second login cookie
} else {
$rootScope.authenticated = false;
$rootScope.session = null;
}
console.log($rootScope.session)
callback && callback();
}).error(function() {
$rootScope.authenticated = false;
callback && callback();
});
}
return {
authenticate: function(credentials){
authenticate(credentials, function() {
if ($rootScope.authenticated == true) {
$rootScope.authenticationError = false;
if ($rootScope.session.principal.admin == true){
$location.path("/admin/manage");
} else{
$location.path("/user");
}
} else {
$rootScope.authenticationError = true;
$location.path("/login");
}
});
},
// called by refreshing browser
checkLoggedIn: function(){
authenticate();
},
logout: function(){
$http.post('/logout', {})["finally"](function() {
$rootScope.authenticated = false;
$rootScope.session = null;
$location.path("/login");
});
}
};
}
编辑 3: 我现在提到,如果未定义 cookie,this link 中的方法 loadToken() 仅在记录后调用退出并刷新浏览器(首次登录)。然后显示令牌,我再次登录。但在每一次尝试之后它仍然很好用..
编辑 4: 所以我没有意识到,在第一个被禁止的 POST-请求(在 Edit3 中是 /logout)之后,令牌到达了我的模板。刷新浏览器后,我的所有请求都被允许,因为现在每个请求都会发送 cookie。但是如何解决这个问题?
我的解决方案:
//WebSecurityConfigurerAdapter:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
....
.addFilterAfter(new CsrfCustomFilter(), CsrfFilter.class).and()
.csrf().csrfTokenRepository(csrfTokenRepository());
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
public class CsrfCustomFilter extends OncePerRequestFilter{
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
}