Spring Security + Angular App REST Token Based Authentication = 403 Forbidden on POST
Posted
技术标签:
【中文标题】Spring Security + Angular App REST Token Based Authentication = 403 Forbidden on POST【英文标题】: 【发布时间】:2015-11-16 14:18:39 【问题描述】:我有一个应用程序,它在前端有 Angular 组件,在后端有 Java。我正在使用基于令牌的身份验证来提供安全性。但是我遇到了一个问题,当我发出 POST 请求时,我得到 403-Forbidden 状态码。所有 GET 请求都可以正常工作。我检查了我在 Java 端的所有实现,看起来还不错。我从 ***.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.
【问题讨论】:
【参考方案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
【讨论】:
以上是关于Spring Security + Angular App REST Token Based Authentication = 403 Forbidden on POST的主要内容,如果未能解决你的问题,请参考以下文章
Angular集成Spring Boot,Spring Security,JWT和CORS
Angular 2/Spring Security CSRF 实现问题
Angular 4.0 + Spring boot + Spring Security:TemplateInputException:解析模板“登录”时出错
如何使用 Spring Security + Angular 登录/验证