当前位置: 首页 > 知识库问答 >
问题:

Angular 5无法从HttpXsrfTokenExtractor获取XSRF令牌

诸葛彦
2023-03-14

我试图通过一个到Spring(基本身份验证)安全RESTAPI的绝对URL发出POST请求
读到Angular没有为绝对URL自动将X-XSRF-TOKEN插入请求头之后,我尝试实现一个HttpInterceptor来添加TOKEN。

在我最初的 /signinPOST请求中,我创建了必要的授权:基本标头,以确保Spring验证请求。
返回的响应标头包含预期的set-cookie令牌:

set-Cookie: XSRF-TOKEN=4e4a087b-4184-43de-81b0-e37ef953d755; Path=/

但是,在我的自定义拦截器类中,当我试图从注入的HttpXsrfTokenExtractor中获取下一个请求的令牌时,它返回null。

下面是我拦截器类的代码:

import {Injectable, Inject} from '@angular/core';
import { Observable } from 'rxjs/Rx';
import {HttpInterceptor, HttpXsrfTokenExtractor, HttpRequest, HttpHandler, 
HttpEvent} from '@angular/common/http';


@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {

   constructor(private tokenExtractor: HttpXsrfTokenExtractor) {}

   intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

     let requestMethod: string = req.method;
     requestMethod = requestMethod.toLowerCase();

     if (requestMethod && (requestMethod === 'post' || requestMethod === 'delete' || requestMethod === 'put' )) {
         const headerName = 'X-XSRF-TOKEN';
         let token = this.tokenExtractor.getToken() as string;
         if (token !== null && !req.headers.has(headerName)) {
           req = req.clone({ headers: req.headers.set(headerName, token) });
         }
      }

    return next.handle(req);
   }
}


令牌提取器。getToken()在上述代码中返回null。我希望它从我以前的/sign请求的Spring(Set Cookie)响应头返回令牌

我读了这篇关于创建拦截器的相关文章:
angular4 http客户端csrf不发送x-xsrf-令牌

但是除了以下内容之外,我找不到更多关于HttpXsrfTokenExtractor的文档:
https://angular.io/api/common/http/HttpXsrfTokenExtractor

问题:为什么HttpXsrfTokenExtractor。getToken()返回null?

此外,我添加了拦截器类作为应用程序的提供者。模块
这是我的应用程序。单元ts:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { LocationStrategy, HashLocationStrategy, APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AlertModule } from 'ng2-bootstrap';
import { routing, appRouterProviders } from './app.routing';
import { HttpXsrfInterceptor } from './httpxrsf.interceptor';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './registration/register.component';
import { HomeComponent } from './home/home.component';

@NgModule({
    declarations: [AppComponent,
               LoginComponent,
               RegisterComponent,
               HomeComponent],
    imports: [BrowserModule,
          FormsModule,
          ReactiveFormsModule,
          HttpClientModule,
          HttpClientXsrfModule, // Adds xsrf support
          AlertModule.forRoot(),
          routing],
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
    providers: [
        appRouterProviders,
        [{provide: APP_BASE_HREF, useValue: '/'}],
        [{provide: LocationStrategy, useClass: HashLocationStrategy}],
        [{provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true }]
    ],
    bootstrap: [AppComponent]
})
export class AppModule {}


另一件需要注意的事情是,我在localhost:3000的Node.js上运行Angular前端,在localhost:8080运行Spring Rest后端。它们在不同的端口上,因此使用绝对网址进行超文本传输协议请求的原因。当来自不同域名上的请求响应时,浏览器会阻止设置Cookie工作吗?

我还能错过什么吗?

谢谢你的任何帮助。

----------------------------------------------
[于2018年1月7日更新]

修复

我使用Webpack dev server为Angular代码提供服务。我通过为指向后端RESTAPI的URL配置代理来解决这个问题

这意味着从浏览器发出的所有请求现在只能发送到端口3000处的dev服务器,即使对于Rest API调用也是如此
当webpack dev服务器看到任何带有配置模式的请求URL(例如/api/…)时,它替换为对上的后端服务器的调用http://localhost:8080(就我而言)

这是我在我的网页的devServer部分添加的内容。dev.jshtml" target="_blank">文件:

proxy: {
    '/api': {
    'target': 'http://localhost:8080',
    'pathRewrite': {'^/api' : ''}
    //Omits /api from the actual request. E.g. http://localhost:8080/api/adduser -> http://localhost:8080/adduser
    }
}



通过这种设置,我不再从Angular代码发出跨域(跨原点)请求,也不再使用绝对URL。这大大简化了事情,因为我不再与角度XSRF(CSRF)机制作斗争。它只是默认工作。我也不需要使用HttpInterceptor手动将X-XSRF-TOKEN插入其中。

设置dev服务器代理的另一个好处是,客户端请求不再是绝对的,因此我不需要为生产更改所有restapi调用。

我希望这对任何遭受同样问题/理解的人都有用。

网页包开发服务器代理文档参考:
https://webpack.js.org/configuration/dev-server/#devserver-代理

共有1个答案

楚骞尧
2023-03-14

由于您使用不同的端口(3000

 类似资料:
  • 我用JHipster 5.1.0生成了一个UAA服务器。我选择PostgreSQL作为数据库类型。 它连接到我的jhipster注册表,然后我生成了一个微服务和一个网关,如下所示: 启动网关进行用户登录后,它无法获取访问令牌并引发错误: 2018-07-23 17:32:53.378调试7228---[XNIO-2 task-10]c.c.c.a.g.a.AccessControlFilter:访

  • 我试图使用请求模块向https://accounts.spotify.com/api/token发出POST请求,以便获得访问令牌。我已经用我的Spotify开发帐户注册了重定向URI。这是我的快速<代码>/重定向 路由。 有人能看到这里可能出了什么问题吗?每次我得到的都是一个不伦不类的“哎呀!出了问题”错误页面。

  • Spring OAuth2实现多因素身份验证的完整代码已经上传到文件共享站点的这个链接。下面给出了在几分钟内在任何计算机上重新创建当前问题的说明。

  • 我试图使用从Spring应用程序中的公共客户端获取访问令牌。 谁能帮我弄清楚我做错了什么吗?

  • 我有一个以下格式的日期,我需要解析它,并转换成一个纪元时间。 关于我做错了什么有什么帮助吗?

  • 当我这样做的时候 如何解析datetime字符串,以便将其解释为始终来自时区“欧洲/柏林”?