【问题标题】:Spring Security + Angular App REST Token Based Authentication = 403 Forbidden on POSTSpring Security + Angular App REST Token Based Authentication = 403 Forbidden on POST
【发布时间】:2015-11-16 14:18:39
【问题描述】:

我有一个应用程序,它在前端有 Angular 组件,在后端有 Java。我正在使用基于令牌的身份验证来提供安全性。但是我遇到了一个问题,当我发出 POST 请求时,我得到 403-Forbidden 状态码。所有 GET 请求都可以正常工作。我检查了我在 Java 端的所有实现,看起来还不错。我从 StackOverFlow.com 和其他论坛查看了其他解决方案,他们建议禁用 CSRF。即使我实现了这一点,我仍然得到 403。有人对此有任何想法吗?提前致谢,这是我的代码。

这是我的 security.xml

<security:http 
        realm="Portected API" 
        use-expressions="true" 
        auto-config="false" 
        create-session="stateless"
        entry-point-ref="unauthorzedEntiryPoint"
        authentication-manager-ref="authenticationManager">
        <security:csrf disabled="true"/>
        <security:custom-filter ref="authenticationTokenProcessingFilter" position="FORM_LOGIN_FILTER"/>
        <security:intercept-url pattern="/foo" method="POST" access="hasAnyRole('USER', 'ADMIN')"/>
        <security:intercept-url pattern="/bar" method="POST" access="hasAnyRole('USER', 'ADMIN')"/>
    </security:http>

如您所见,我在代码的第 8 行禁用了 CSRF。这是我剩下的 XML 部分。

<security:global-method-security secured-annotations="enabled"/>

<security:authentication-manager id="authenticationManager">
    <security:authentication-provider user-service-ref="userDetailService">
            </security:authentication-provider>
</security:authentication-manager>


<beans:bean id="unauthorzedEntiryPoint" class="org.sec.config.security.UnauthorizedEntryPoint"/>

<beans:bean id="authenticationTokenProcessingFilter" class="org.sec.config.security.AuthenticationTokenProcessingFilter">
    <constructor-arg ref="userDetailService"/>
</beans:bean>

<beans:bean id="userDetailService" class="org.sec.config.security.UserDetailService"/>

<beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

在我的 Angular 方面,我这样调用资源:

Restangular.all('bar').post(barModel, {}, {'Sec-Token': $localStorage.userToken})
      .then(function (response) {
        deferred.resolve(response);
        vm.currentBlog = response;
        //rest of the code.
}

【问题讨论】:

    标签: java angularjs spring-security csrf http-status-code-403


    【解决方案1】:

    1) 如下图添加过滤器类

    public class CsrfHeaderFilter 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);
    }
    }
    

    2) 更新安全配置类以包含上述过滤器,如下所示

      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
      import org.springframework.security.config.annotation.web.builders.HttpSecurity;
      import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
      import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
      import org.springframework.security.web.csrf.CsrfFilter;
      import org.springframework.security.web.csrf.CsrfTokenRepository;
      import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
    
      @Configuration
      @EnableWebSecurity
      public class SecurityConfig extends WebSecurityConfigurerAdapter{
    
    
    
      protected void configure(HttpSecurity http) throws Exception {
        http
        .httpBasic().and()
        .authorizeRequests()
          .antMatchers("/login", "/login?logout" ).permitAll().anyRequest()
          .authenticated().and()
        .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class).csrf().csrfTokenRepository(csrfTokenRepository());
     }
    
    private CsrfTokenRepository csrfTokenRepository() {
          HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
          repository.setHeaderName("X-XSRF-TOKEN");
          return repository;
        }
    

    }

    3) 现在不需要在 Restangular post call 中包含任何额外的 header,示例代码如下所示。

    $Restangular.all('/addData').customPOST(
                         {amount:$scope.newExpense.amount, reason:$scope.newExpense.reason,dateStr:''+$scope.newExpense.date  },
                        '',
                        {},
                        {
                            'ContentType':'application/x-www-form-urlencoded'
                        }
                    ).then(function() {
    

    来源:https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii

    【讨论】:

      猜你喜欢
      • 2015-09-19
      • 2021-02-26
      • 2016-03-11
      • 2015-12-02
      • 2014-07-31
      • 2014-11-24
      • 2013-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多