HttpClient 发布请求延迟操作 - Angular 16

问题描述 投票:0回答:1

所以,我在这里尝试使用 .Net Core API 在 Angular 中实现 JWT。当我启动 Angular 服务器并运行应用程序时,会发生以下情况:

  • 使用正确的凭据尝试失败,请重试,然后就可以了。
  • 尝试使用错误的凭据失败,重试然后失败。
  • 尝试使用正确的凭据失败,请重试但使用错误的凭据,然后登录即可。

我想澄清一下,登录与否取决于 JWT 令牌已作为值存储在 localStorage 中,这意味着 API 调用在某些时候有效,只是没有在正确的时间以某种方式进行验证。

所以,为了揭开谜底,这里是有问题的代码:

这将是 AuthService:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { User } from 'src/app/models/User';


const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type':'application/json;charset=UTF-8'
  })
}


@Injectable({
  providedIn: 'root'
})
export class AuthService{

  public loggedIn = false;

  constructor(private httpClient:HttpClient) { }

  login(user: User){
    // Set the User object with the corresponding credentials as the request body
    const body = JSON.stringify(user);
    // Send the post request with its corresponding headers and body
    this.httpClient.post<any>("https://localhost:7054/login", body, httpOptions)
    .subscribe(data => {
      // Here, the data received from the API is known (as I developed it myself):
      // it will only contain the token if successful, and will return a bad request
      // with a blank token if it fails, so the only scenario where the token may
      // be valid is through a HTTP 200 response.
      localStorage.setItem("token", data.token);
    });
  }
}

这将是 HomeComponent.ts

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AuthResponse } from 'src/app/models/AuthResponse';
import { User } from 'src/app/models/User';
import Swal from "sweetalert2";
import { AuthService } from 'src/app/services/auth/auth.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})

export class HomeComponent {
  user: User = new User();

  constructor(private router: Router, private authService:AuthService) {
  }

  token: AuthResponse = new AuthResponse();

  //Login method
  login(username: string, password: string) {

    // - User authentication
    // The verification occurs in the backend for security purposes.
    
    // Validate credentials are not blank
    if(username != "" || password != ""){

      // Create a new User object, which will be passed to the API as request body
      let user = new User();
      user.email = username;
      user.pass = password;

      // Call the auth service
      this.authService.login(user);
      
      // If the previous operation went well, the token must be stored, and we should be able to log in
      if(localStorage.getItem("token")){
        this.router.navigate(['/home']);
      }
      // If the request returns nothing, the credentials are incorrect, therefore an error alert will be sent, plus the token is set to blank
      else{
        this.sendError("Credentials are incorrect.")
        localStorage.setItem("token", "");
      }
    }
    else{
      // If the credentials are blank, therefore an error alert will be sent, plus the token is set to blank
      this.sendError("Please type your credentials.")
      localStorage.setItem("token", "");
    }
  }

  sendError(error:string){
    Swal.fire({
      icon: 'error',
      title: 'Error',
      text: error,
    })

  }
}

因此,如果有人能指出这种奇怪行为的原因,我将不胜感激。我确信我遗漏了一些东西或者明显做错了,我只是无法指出它。

预先感谢您的帮助。

我尝试使用拦截器来处理响应,但它们似乎对奇怪的行为没有帮助。

我尝试过强制进行令牌验证,但似乎也没有帮助,因为令牌类型会在尝试之间被缓存。

angular typescript post jwt
1个回答
0
投票

我看到了很多问题。

首先在这里:

  if(localStorage.getItem("token")){
    this.router.navigate(['/home']);
  }
  // If the request returns nothing, the credentials are incorrect, therefore an error alert will be sent, plus the token is set to blank
  else{
    this.sendError("Credentials are incorrect.")
    localStorage.setItem("token", "");
  }

您的 else 语句正在设置令牌。所以,当一个人第二次点击“登录”时;无论登录成功与否,应用程序都会导航至回家路线。

此外,登录代码是异步的(它应该是这样),但您正在同步运行检查。所以这一段代码(就在我引用的上一节的上方)可能是在登录功能完成之前检查令牌是否存在。

 // Call the auth service
  this.authService.login(user);
  
  // If the previous operation went well, the token must be stored, and we should be able to log in
  if(localStorage.getItem("token")){

一个可能的修复方法是让 authService 返回一个 Observable。另外,使用管道运算符而不是 subscribe() 方法处理令牌。

login(user: User){
    // Set the User object with the corresponding credentials as the request body
    const body = JSON.stringify(user);
    // Send the post request with its corresponding headers and body
    return this.httpClient.post<any>("https://localhost:7054/login", body, httpOptions)
    .pipe(tap(data => {
      // Here, the data received from the API is known (as I developed it myself):
      // it will only contain the token if successful, and will return a bad request
      // with a blank token if it fails, so the only scenario where the token may
      // be valid is through a HTTP 200 response.
      localStorage.setItem("token", data.token);
    }));
  }

我使用了tap,不过在这种情况下可能有更好的运算符可以使用。

然后调整组件代码以订阅 Observable,以便在 login() 方法完成后处理结果:

  // Call the auth service
  this.authService.login(user).subscribe(() ==> {
  // If the previous operation went well, the token must be stored, and we should be able to log in
     if(localStorage.getItem("token")){
       this.router.navigate(['/home']);
     }
    // If the request returns nothing, the credentials are incorrect, therefore an error alert will be sent, plus the token is set to blank
     else{
       this.sendError("Credentials are incorrect.")
       localStorage.setItem("token", "");
     }

  });
  

我建议您根据服务器返回的错误代码来处理错误,而不是检查令牌是否存在。

免责声明:所有这些代码都是在浏览器中编写的并且未经测试,但应该演示一种替代方法,该方法将修复我见过的一些逻辑错误。

© www.soinside.com 2019 - 2024. All rights reserved.