Angular 10 - 端点访问可以从邮递员而不是 Angular

Angular 10 - Endpoint access works from postman but not from Angular

我有一个前端 angular 应用程序,我是 运行 来自 localhost:4200

我还有一个后端 api 应用程序,我是 运行 来自 localhost:8080

我也有 postman 运行,我在创建 angular 前端之前用它来测试这些端点。

我的问题是 localhost:8080/ 在通过邮递员调用 localhost:8080/sign-in 后有效,但在通过我的 angular 前端调用 localhost:8080/sign-in

我可以通过 postman 使用路由 localhost:8080/sign-in,它会登录用户并设置 session cookie。 这是结果:

响应:

It returns the user object here as JSON

Header:

Access-Control-Allow-Origin:    
Access-Control-Expose-Headers   Set-Cookie
Content-Type    application/json; charset=UTF-8
Set-Cookie  session_=RTZCYXOW3ILNKOOZQOZKEC4Y3J3YPOVUGGA6TI46ZLRX5UAWS77O7TGE74ZEFQEOTZLTCKRTCYJJ57OT24KUPPMBPYOXWBZRXF54PGA; Path=/; Expires=Sun, 29 Nov 2020 09:33:43 GMT; Max-Age=604800
Vary    Origin
X-Request-Id    gTCSwvwm4m8oLDqy99fkhqAeWgrddnjl
Date    Sun, 22 Nov 2020 09:33:43 GMT
Content-Length  658

然后我有另一个端点:localhost:8080/ 需要用户登录才能访问。

如果他们已登录:

响应:

“Valid”

Header:

Access-Control-Allow-Origin:    
Access-Control-Expose-Headers   Set-Cookie
Content-Type    application/json; charset=UTF-8
Vary    Origin
X-Request-Id    mRy9w40wEKx4zI2h4JuaMAZ2CppbvzHR
Date    Sun, 22 Nov 2020 09:34:47 GMT
Content-Length  8

如果他们没有登录:

响应:

"access denied”

Header:

Access-Control-Allow-Origin: 
Access-Control-Expose-Headers: Set-Cookie
Content-Type: application/json; charset=UTF-8
Vary: Origin
X-Request-Id: eRQJwPIXQnAOavpgkhobNoJnKgbQmDpE
Date: Sun, 22 Nov 2020 09:36:11 GMT
Content-Length: 18

现在,我可以从我的 angular 应用程序调用 localhost:8080/sign-in 端点。 这确实 return 用户作为 JSON object 与邮递员相同。

但是我不认为它正在设置 cookie,因此当我从我的 angular 应用程序调用 localhost:4200/ 端点时,它会给出错误:[ HTTP/1.1 403 Forbidden 1ms] 如果我在注销时尝试访问该端点,这与我从邮递员那里得到的错误相同。

我确保在尝试 localhost:8080/ 之前调用了 localhost:8080/sign-in angular 前端(先尝试设置 cookie)

这是我后台的相关配置api:

这是session商店配置

store.Options(sessions.Options{
    Path: "/",
    MaxAge:   86400 * 7,
    HttpOnly: false,    
})

这是中间件配置

e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
    AllowOrigins:  []string{"http://localhost:4200"},
    AllowHeaders:  []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAccessControlAllowCredentials},
    ExposeHeaders: []string{echo.HeaderSetCookie},
    AllowCredentials: true,
}))

这是我在 angular 前端登录的服务和组件:

auth-http.service.ts

  login(email: string, password: string): Observable<Response> {

    let headers = new HttpHeaders({'Content-Type': 'application/json'});
    headers.set('access-control-allow-origin',"http://localhost:4200/");
    headers.set('withCredentials', "true");
  

   
    let result =  this.http.post<any>(`${API_URL}/sign-in`,   { email: email, password: password }, { headers });

    return result;


  }

  test(): Observable<Response> {

    let headers = new HttpHeaders({'Content-Type': 'application/json'});
    headers.set('access-control-allow-origin',"http://localhost:4200/");
    headers.set('withCredentials', "true");
    
    let result =  this.http.get<any>(`${API_URL}/`, { headers });

    return result;

  }

auth.service.ts

  login(email: string, password: string): Observable<UserModel> {
 
    this.isLoadingSubject.next(true);

    return this.authHttpService.login(email, password).pipe(

      map((result: Response) => {

        // undefined
        console.log(result.headers)
       
        console.log(result);
        // pass in the auth here
       
  
        return result;
      }),
      //switchMap(() => this.getUserByToken()),
      catchError((err) => {
        console.error('err', err); // here
        return of(undefined);
      }),
      finalize(() => this.isLoadingSubject.next(false))
    );
  }

  test(): Observable<any> {
 
    this.isLoadingSubject.next(true);

    return this.authHttpService.test().pipe(

      map((result: Response) => {
        return result;
      }),
      //switchMap(() => this.getUserByToken()),
      catchError((err) => {
        console.error('err', err); // here
        return of(undefined);
      }),
      finalize(() => this.isLoadingSubject.next(false))
    );
  }

login.component.ts

  submit() {
    this.hasError = false;
    const loginSubscr = this.authService
      .login(this.f.email.value, this.f.password.value)
      .pipe(first())
      .subscribe((user: UserModel) => {
        console.log(user);
        if (user) {
          this.router.navigate([this.  returnUrl]);
        } else {
          this.hasError = true;
        }
      });
    this.unsubscribe.push(loginSubscr);
  }

  test() {
       this.hasError = false;
    const loginSubscr = this.authService
      .test()
      .pipe(first())
      .subscribe((res: any) => {
        console.log(res);
       if (res) {
          console.log(res)
        } else {
          this.hasError = true;
        }
      });
this.unsubscribe.push(loginSubscr);
  }

为了测试 localhost:8080/ 端点,我刚刚在登录 html 组件上创建了一个测试按钮,然后调用测试服务以查看它是否可以访问localhost:8080/ 端点。

通过使用:

  const options = {withCredentials: true, 'access-control-allow-origin': "http://localhost:4200/", 'Content-Type': 'application/json'} 

而不是另一种设置方式headers。