0

我正在使用 Spring Security 来使用 AngularJS 保护我的 Spring Data REST Web 应用程序。

我的 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());
}

我通常遵循链接来实现我的目标。

现在,如果我第一次登录自己,则$cookies.get("XSRF-TOKEN")返回未定义的角度请求并且不会阻止对我的数据库的每个请求。

但是在注销并再次登录后,它会返回 cookie,并且允许每个数据库请求。

这只会在每第二次登录时发生,所以:

  1. 不明确的

  2. 曲奇饼

  3. 不明确的

  4. 曲奇饼

  5. 不明确的

    ...

所以现在我希望有人可以在不深入了解我的结构的情况下帮助我,但如果需要,我会这样做。

提前致谢。

编辑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 未定义,则仅在注销并刷新浏览器(首次登录)后才会调用此链接中的 loadToken() 方法。然后显示令牌,我再次登录。但是在每秒钟尝试之后它仍然很好用..

编辑 4:所以我没有认识到,在第一个禁止的 POST 请求(在 Edit3 中是 /logout)之后,令牌到达我的模板。刷新浏览器后,我的所有请求都被允许,因为现在每个请求都会发送 cookie。但是如何解决这个问题?

4

1 回答 1

-1

我的解决方案:

//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);
    }
}
于 2017-01-20T09:08:44.310 回答