【问题标题】:spring boot angular js http:/localhost:8080/logout 403 forbidden errorspring boot angular js http://localhost:8080/logout 403 禁止错误
【发布时间】:2018-01-07 04:40:48
【问题描述】:

我无法解决这个问题。

我尝试验证登录注销示例here。登录正常,但是当我尝试注销时,浏览器给出 NetworkError : 403 disabled localhost:8080/logout is disabled.

在我看来,我应该在 ui 端的每个请求中添加令牌标头。但我不知道该怎么做?

这里是浏览器开发者工具消息:

发布 403 {"timestamp":1501570024381,"status":403,"error":"Forbidden","message":"Invalid CSRF Token 'null' 是 在请求参数 '_csrf' 或标头 'X-CSRF-TOKEN' 上找到。","path":"/helpdesk/logout"}

这是我的角度注销功能:

 $scope.logout = function() {
    $http.post('logout',{}).success(function() {
      $rootScope.authenticated = false;
      $location.path("/home");
    }).error(function(data) {
      $rootScope.authenticated = false;
    });
  }

这是我的 SpringSecurityConfig 配置方法:

 @Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .httpBasic().and()
            .authorizeRequests()
            .antMatchers("/index.html","/pages/**","/","/webjars/**")
            .permitAll()
            .anyRequest()
            .authenticated().and().logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll()
            .logoutSuccessHandler(logoutSuccess)
            .deleteCookies("JSESSIONID").invalidateHttpSession(false)
            .and()
            .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);

}

我该如何解决这个问题?如何将令牌标头添加到所有请求?你能帮帮我吗?

【问题讨论】:

  • 您不需要明确地这样做$rootScope.authenticated = false;$location.path("/home");。您的配置应该足以注销用户,您应该能够执行简单的发布请求以注销。但是,了解您正在使用的 SpringSec 版本会很有帮助。您可能希望在您的发布请求中包含其他标头。
  • 我必须设置 $rootscope.authenticated = false 因为某些视图隐藏或显示此参数的状态。我会尝试这个解决方案,如果它可以工作我会用不同的方式来解决这个问题。谢谢。
  • 我尝试了您的解决方案,但没有奏效。我编辑了这个问题。
  • 顺便说一句,我检查了您所关注教程的链接。乍一看,他们正在描述如何处理CSRF 令牌。我的回答可能没用
  • 您需要在调用中将 csrf 令牌发送到 spring 控制器,因为这就是 Spring 安全性的工作方式。基于这些 csrf 令牌,只有调用得到验证和授权。

标签: java angularjs spring-boot spring-security


【解决方案1】:

我解决了我的问题:

我在研究goole时首先找到this sample

之后我像这样应用了相同的拦截器:

app.factory('CsrfTokenInterceptorService', ['$q',
function CsrfTokenInterceptorService($q) {

    // Private constants.
    var CSRF_TOKEN_HEADER = 'X-CSRF-TOKEN',
        HTTP_TYPES_TO_ADD_TOKEN = ['DELETE', 'POST', 'PUT'];

    // Private properties.
    var token;

    // Public interface.
    var service = {
        response: onSuccess,
        responseError: onFailure,
        request: onRequest,
    };

    return service;

    // Private functions.
    function onFailure(response) {
        if (response.status === 403) {
            console.log('Request forbidden. Ensure CSRF token is sent for non-idempotent requests.');
        }

        return $q.reject(response);
    }

    function onRequest(config) {
        if (HTTP_TYPES_TO_ADD_TOKEN.indexOf(config.method.toUpperCase()) !== -1) {
            config.headers[CSRF_TOKEN_HEADER] = token;
        }

        return config;
    }

    function onSuccess(response) {
        var newToken = response.headers(CSRF_TOKEN_HEADER);

        if (newToken) {
            token = newToken;
        }

        return response;
    }
}]);

并添加到 app.config 方法中:

$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
$httpProvider.interceptors.push('CsrfTokenInterceptorService');

但现在我遇到了另一个问题。浏览器开始打开自定义身份验证弹出窗口。我必须解决这个问题。

【讨论】:

    【解决方案2】:

    CSRF 令牌将由 SpringSec 检查所有postrequests。因此,您可以每次都包含它,也可以禁用它。 XML 配置看起来像这样:

    <http ...... >
    
      <!-- ... -->
      <csrf disabled="true"/>
    
    </http>
    

    或者只是在你的config 中添加以下内容:

     @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .httpBasic().and()
                .authorizeRequests()
                .antMatchers("/index.html","/pages/**","/","/webjars/**")
                .permitAll()
                .anyRequest()
                .authenticated().and().logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll()
                .logoutSuccessHandler(logoutSuccess)
                .deleteCookies("JSESSIONID").invalidateHttpSession(false)
                .and()
                .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
    
    }
    

    这样你就不需要关心它的包含了。要正确处理CSRF Tokens,请查看Spring Security’s Cross Site Request Forgery (CSRF) support.

    附:让我知道以防万一它没有帮助或至少为您指明正确的方向。

    【讨论】:

    • 感谢您的关注。那么,我们必须禁用 csrf 吗?我的意思是我们必须在我们的应用程序上保护会话,对吗?如果我猜对了,我会发送 csrf 令牌作为来自 angular js 的所有请求的标头。你知道我该怎么做吗?
    • 不幸的是,我不熟悉 angular,但我想您所关注的 Spring Sec 支持和教程的链接应该会给您一些见解。祝你好运:)
    • 请检查 stackoverflow.com/a/45455423/5707108 这个。
    猜你喜欢
    • 2020-01-17
    • 2018-01-14
    • 1970-01-01
    • 2021-09-04
    • 2021-03-05
    • 1970-01-01
    • 2011-07-12
    • 2019-05-27
    • 2018-03-14
    相关资源
    最近更新 更多