我已经获得了一个Spring启动RESTful服务,Spring安全配置如下:
__dict__
&安培;
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and()
/*.formLogin().loginPage("/auth")
.permitAll().and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and().httpBasic().and()*/
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
}
我正在使用Angular 4(最新版本)调用RESTful服务。它正在做一个帖子请求抱怨并抛出403 Forbidden"无法验证提供的CSRF令牌,因为找不到你的会话。"这是预期的,因为我在发送发布请求时没有设置X-CSRF-TOKEN标头但是此标头确实存在: - 设置Cookie:XSRF-TOKEN =;路径= /
角:
auth.service.ts:
public class CsrfHeaderFilter extends OncePerRequestFilter {
private static final String CSRF_COOKIE_NAME = "XSRF-TOKEN";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
response.addHeader("X-CSRF-TOKEN", csrf.getToken());
Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);
String token = csrf.getToken();
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie(CSRF_COOKIE_NAME, token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
app.module.ts(注意:使用HttpClient发布请求):
const body = 'SOMERANDOMKEY1111';
const headers = new HttpHeaders().set('Content-Type', 'application/json').set('withCredentials', 'true');
return this._http.post(this.endpoint + this.auth, body, {
headers: headers
});
我已经关注了this并阅读了相关文档,但似乎无法实现这一目标。
答案 0 :(得分:2)
当我开始使用Spring和angular5时,我遇到了同样的问题:
问:如何在每个由angular发出的请求上设置X-CSRF令牌?
Sol: 服务器端:
首先,您需要在服务器端配置csrf安全性
在服务器端,您需要编写一个在浏览器上设置cookie的api(cookie内的X-CSRF令牌),而该api却没有任何抵押就被击中(禁用此api的csrf,假设api名称为/ info)
注意:/ info该API仅在首次加载angular应用时被调用一次(您需要在要加载到angular应用中的首页中添加此信息)
角侧:
当应用程序加载到angular的第一页/组件上时,在oninit内,您需要将此路由称为“ / info”(您需要在angular中创建服务并在此处调用此api) 我在我的layout / navbar组件上进行了设置,因为在加载应用程序时,该组件是第一个加载的组件
然后在app.module.ts内部,我们需要导入
从'@ angular / common / http'导入{HttpClientModule};
并将此模块添加到导入数组中:
@NgModule({ imports: [
HttpClientXsrfModule.withOptions({
cookieName: 'XSRF-TOKEN',
headerName: 'X-XSRF-TOKEN',
})]
-然后在服务内部,您需要按以下方式更改请求:user.service.ts
registeruser(data) {
console.log(data)
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers, withCredentials: true });
return this.http.post(this.url + '/avssymbuaa/api/register', data, options).map(res => res.json());
}
import {Http,标头,RequestOptions,响应,URLSearchParams} 来自“ @ angular / http”;
也许这可以帮助您,谢谢
答案 1 :(得分:0)
响应被禁止,因为spring服务器或您的代理期望在标头中收到X-CSRF令牌而您没有发送它。
1.请确保您正在执行 POST (在LOG IN上)方法以接收CSRF-TOKEN
2.存储在cookies或 localstorage
中收到的令牌3.制作帖子并将标记添加到标题中:
let headers = new Headers({ 'XSRF-TOKEN', 'the token received after login' });
let options = new RequestOptions({ headers: headers });
return this.http.post(url,body,options);
答案 2 :(得分:0)
如果您的Angular UI
和RESTful服务位于不同的域中,则您的Angular代码无法读取后端设置的Cookie。要在本地工作区中解决这个问题,您可以set up cli proxy
但对于生产,如果您使用的是Apache HTTP服务器,则需要设置反向代理。这是一个例子:
<VirtualHost *:443>
ServerName localhost
SSLEngine on
SSLProxyEngine On
SSLCertificateFile conf/ssl/newfile.crt
SSLCertificateKeyFile conf/ssl/newfile.key
ProxyPass /api/ https://yoursite/api/
ProxyPassReverse /api/ https://yoursite/api/
</VirtualHost>
<VirtualHost *:80>
ServerName localhost
ProxyPass /api/ http://yoursite/api/
ProxyPassReverse /api/ http://yoursite/api/
</VirtualHost>