对于基于Cookie的身份验证,我的服务器向我的ANGLE应用程序发送Set-Cookie.但是,应用程序不会在进一步的请求中传回该值.以下是我的代码.

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
  withCredentials: true //this is required so that Angular returns the Cookies received from the server. The server sends cookies in Set-Cookie header. Without this, Angular will ignore the Set-Cookie header
};

public getUserProfile(){
    console.log('contacting server at '+this.API_URL +this.GET_USER_PROFILE_URL+"with httpOptions "+httpOptions);
    return this.http.get(this.GET_USER_PROFILE_URL,httpOptions )
      .map(response=>{
        console.log('response from backend service',response);
        let result= <ServerResponse>response; 
        console.log("result is "+result.result+' with additional information '+result.additionalInformation)
        return result;
      })
      .catch(this.handleError);
  }

在我的代码200OK中,服务器按如下方式发送cookie(此处未显示)

Set-Cookie: id=...

但是,下一条消息的cookie中没有id,因此服务器返回401.如果我使用浏览器的调试工具手动添加Cookie,那么我得到200OK.因此,我确信是cookie中缺少id值导致了问题.

我做错了什么?我是否需要显式存储在Set-Cookie中收到的cookie,并在进一步的请求中显式添加它?

更新-

我加了几张照片来解释我的意思

在签名期间,客户端发送一个与CSRF相关的cookie.我不认为这是必需的,因为客户端也会发送CSRF头,但出于某种原因,它确实会发送.服务器用带有id的Set Cookie进行响应

enter image description here

然后,当我请求配置文件时,客户端再次发送csrf cookie,但不发送id cookie.

enter image description here

推荐答案

我终于找到了问题所在.这次旅行比结果更令人满意,所以让我把它分解成我解决问题所采取的步骤.

总而言之,这不是Angular的问题.我发送的cookies 上有secureCookie个标记.当我在没有https的情况下测试应用程序时,angular应用程序似乎没有使用(或访问)200 OK中接收到的Set-Cookie报头.

我最初向服务器发送登录请求并处理其响应的代码是

  return this.http.post(this.SIGNIN_USER_URL,body,httpOptions)
      .map(response=>{
        console.log('response from backend service',response);
        let result= <ServerResponse>response; 
        console.log("result is "+result.result+' with additional information '+result.additionalInformation)
        return result;
      })
      .catch(this.handleError);

我没有使用observe: 'response'选项,这意味着响应将只包含正文,而不是标题.我将代码改为following,这样我就可以看到接收到了哪些头.

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
 
withCredentials: true, 
observe: 'response' as 'response'
};  

public signinUser(user:UserSigninInfo):any{
    console.log('contacting server at '+this.API_URL +this.SIGNIN_USER_URL +" with user data "+user+ " with httpOptions "+httpOptions.withCredentials + ","+httpOptions.headers ); 

    let signinInfo= new UserSignin(user);
    let body = JSON.stringify(signinInfo);
    return this.http.post(this.SIGNIN_USER_URL,body,httpOptions)
      .catch(this.handleError);
  }

上面的代码被调用如下.我更改它以获取响应中的标题

return this.bs.signinUser(user).subscribe((res:HttpResponse<any>)=>{console.log('response from server:',res);
  console.log('response headers',res.headers.keys())
} );

我还创建了一个拦截器来打印传入和传出的消息(复制自SO)

import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from "@angular/common/http";
import {Injectable} from "@angular/core";
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/do';

@Injectable()
export class CustomInterceptor implements HttpInterceptor {

  constructor() {
  }

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

    console.log("outgoing request",request);
    request = request.clone({
      withCredentials: true
    });
    console.log("new outgoing request",request);

    return next
      .handle(request)
      .do((ev: HttpEvent<any>) => {
        console.log("got an event",ev)
        if (ev instanceof HttpResponse) {
          console.log('event of type response', ev);
        }
      });
  }
}

当我开始调试时,我注意到虽然服务器发送了10个标题,但只打印了9个

来自服务器的标题

enter image description here

在控制台上打印消息(缺少Set-Cookie!我的应用程序需要获取身份验证cookie的标题)

0: "Content-Length"
​
1: "Content-Security-Policy"
​
2: "Content-Type"
​
3: "Date"
​
4: "Referrer-Policy"
​
5: "X-Content-Type-Options"
​
6: "X-Frame-Options"
​
7: "X-Permitted-Cross-Domain-Policies"
​
8: "X-XSS-Protection"
​
length: 9

这给了我一个方向,应用程序没有看到Set-Cookie头.我原以为我可以通过在play framework exposedHeaders = ["Set-Cookie"]中添加CORS策略来解决这个问题,但这不起作用.后来我更仔细地看了看cookies ,注意到它的背景

Set-Cookie: id=...Secure; HTTPOnly

这让我觉得我的cookie设置可能不适合我的环境(localhost,没有HTTPS).我改变了Silhoutte的cookie设置

val config =  CookieAuthenticatorSettings(secureCookie=false)

成功了!

虽然我会让上面的代码在secureCookie上工作,而且这不是Angular 的问题,但我希望有些人会发现这种方法很有帮助

Angular相关问答推荐

单元测试 case 模拟store 中的行为主体

角material 17 -如何从Style.scss中的主题中获取原色

未触发HTTP拦截器

Angular router-outlet 未渲染

截取提取后端S获取添加授权头的请求

当嵌套在异步容器中时,S会阻止具有动态值的ionic 段工作吗?

react 形式之间的循环关系

对REST后端的Angular/Priming过滤器请求导致无限循环

Observable转换为Observable

NgRx Effects 抛出类型错误,我不知道发生了什么

Angular 测试被认为是成功的,即使有错误

包含与 ngFor 相关内容的 HTML 输入

如何在 Angular 中创建通用的可重用组件

错误:在工作区外运行 Angular CLI 时,此命令不可用

CORS 策略和 .NET Core 3.1 的问题

Angular ngFor 索引从 1 开始 循环

如何以Angular 获取嵌套表单组的控件

Angular 6在输入键上添加输入

升级到 angular-6.x 会给出Uncaught ReferenceError: global is not defined

Angular2:子组件访问父类变量/函数