Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring security Angular 5无法从HttpXsrfTokenExtractor获取XSRF令牌_Spring Security_Csrf_Webpack Dev Server_Angular5_X Xsrf Token - Fatal编程技术网

Spring security Angular 5无法从HttpXsrfTokenExtractor获取XSRF令牌

Spring security Angular 5无法从HttpXsrfTokenExtractor获取XSRF令牌,spring-security,csrf,webpack-dev-server,angular5,x-xsrf-token,Spring Security,Csrf,Webpack Dev Server,Angular5,X Xsrf Token,我正试图通过绝对URL向Spring(基本身份验证)安全Rest API发出POST请求。 读到Angular没有为绝对URL自动将X-XSRF-TOKEN插入请求头之后,我尝试实现一个HttpInterceptor来添加令牌 在我最初的/signinPOST请求中,我创建了必要的authorization:Basic头,以确保Spring对请求进行身份验证 返回的响应头包含预期的设置cookie标记: Set Cookie:XSRF-TOKEN=4e4a087b-4184-43de-81b0-

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

在我最初的/signinPOST请求中,我创建了必要的authorization:Basic头,以确保Spring对请求进行身份验证
返回的响应头包含预期的设置cookie标记:

Set Cookie:XSRF-TOKEN=4e4a087b-4184-43de-81b0-e37ef953d755;路径=/


但是,在我的自定义拦截器类中,当我尝试从注入的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);
   }
}

另一件需要注意的事情是,我在Node.js上从localhost:3000运行角度前端,从localhost:8080运行弹簧座后端。 它们位于不同的端口上,因此使用绝对URL进行http请求的原因是。当来自不同域上请求的响应时,浏览器是否会阻止Set Cookie工作?

我还会错过什么吗?

谢谢你的帮助

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

修复

我使用Webpack dev server来提供角度代码。我通过为指向后端Rest API的URL配置代理来解决这个问题。

这意味着从浏览器发出的所有请求现在只能发送到位于端口3000的dev服务器,甚至对于restapi调用也是如此。
webpack dev server看到任何带有配置模式(例如/api/…)的请求URL时,它将替换为对上后端服务器的调用(在我的例子中)。

这是我添加到webpack.dev.js文件devServer部分的内容:



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

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

我希望这对遇到同样问题/理解的人有用。

网页包开发服务器代理文档参考:

由于您使用的是不同的端口(3000和8080),因此您正在发出跨源请求,因此您将无法读取从服务器发送的客户端中的cookie。如果希望以这种方式分离客户端和服务器,则需要使用代理,以便客户端和服务器应用程序从相同的协议(http/https)、域和端口提供服务。如果您使用的是Spring Boot,我建议您看看Spring Cloud Netflix,特别是Zuul()。

感谢您的建议,并澄清了我对跨源请求Cookie的理解。我在客户端使用Webpack dev server,因此我通过为rest调用配置代理来解决这个问题。我会更新我的问题来说明我做了什么。嗨,格伦,我也有同样的问题,但我真的不明白问题出在哪里。我从index.html开始开发了一个简单的角度前端。Spring(core+security)是4.3.0版,我已经描述了启用csrf的简单示例,但我从未看到angular(5.2.11)和Spring的标记。你能帮点忙吗?谢谢lot@Bomberlatinos9除非您是从spring应用程序中为angular应用程序提供服务,或者您有一个代理,否则您很可能是在提出跨源请求。我建议你问一个新问题,把你申请表的所有细节都写进去it@dspies您好,我已经将angular应用程序与spring集成,因此所有rest调用都在同一个域中。您会在生产中使用这种方法吗?您是否仅使用代理部署应用程序?
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 {}
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
    }
}