首页 文章

Angular 4无法在标头中设置CSRF-TOKEN

提问于
浏览
-1

我有一个Spring启动RESTful服务,Spring安全配置如下:

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);
    }

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);
}

}

我正在使用Angular 4(最新版本)调用RESTful服务 . 它正在做一个投诉请求抱怨并抛出403 Forbidden“无法验证提供的CSRF令牌,因为找不到你的会话 . ”这是预期的,因为我在发送post请求时没有设置X-CSRF-TOKEN头但是这个头确实存在: - Set-Cookie:XSRF-TOKEN =;路径= /

角度:

auth.service.ts:

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
    });

app.module.ts(注意:使用HttpClient发布请求):

providers: [ ...
{
    provide: XSRFStrategy, useFactory: xsrfFactory
}...]
export function xsrfFactory() {
  return new CookieXSRFStrategy('XSRF-TOKEN', 'XSRF-TOKEN');
}

我已经按照this阅读了文档,但似乎无法使其正常工作 .

3 回答

  • 0

    如果您的 Angular UI 和RESTful服务位于不同的域中,则您的Angular代码无法读取后端设置的cookie . 要在本地工作区中解决此问题,您可以set up cli proxy但是对于 生产环境 ,如果您使用的是Apache HTTP服务器,则需要设置反向代理 . 这是一个例子:

    对于https

    <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>
    

    对于http

    <VirtualHost *:80>
        ServerName localhost
        ProxyPass /api/ http://yoursite/api/
        ProxyPassReverse /api/ http://yoursite/api/
    </VirtualHost>
    
  • 0

    响应被禁止,因为spring服务器或您的代理期望在标头中收到X-CSRF令牌而您没有发送它 .

    1.请确保您正在执行 POST (登录时)方法以接收CSRF-TOKEN

    2.存储在cookie或localstorage中收到的令牌

    3.制作帖子并将标记添加到 Headers 中,如下所示:

    let headers = new Headers({ 'XSRF-TOKEN', 'the token received after login' });
    let options = new RequestOptions({ headers: headers });
    return this.http.post(url,body,options);
    
  • 0

    当我开始使用Spring和angular5时,我遇到了同样的问题:

    问:如何在每个角度设置请求上设置X-CSRF令牌?

    Sol:服务器端:

    • 首先需要在服务器端配置csrf安全性

    • 在服务器端你需要编写一个api,它在浏览器上设置cookie(cookie中的X-CSRF令牌),这个api没有任何证券(在这个api上禁用csrf,假设api名称/信息)

    注意:/ info这个api只在第一次加载角度应用程序时被调用一次(你需要添加它在第一页,这是在角应用程序中加载)

    角边:

    • 当应用程序加载到第一页/组件的角度时,在内部oninit你需要调用这条路线“/ info”(你需要在角度创建服务并在那里调用这个api)我在我的布局/导航栏组件上设置这个因为当app加载此组件是第一个加载的

    • 然后在app.module.ts里面我们需要导入

    从'@ angular / common / http'导入;

    并在导入数组中添加此模块:

    @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());
      }
    
    • 注意:您需要在服务中导入此内容

    从'@ angular / http'导入{Http,Headers,RequestOptions,Response,URLSearchParams};

    可能这个人会帮助你,谢谢

相关问题