如何实现Angular身份验证守卫

huangapple go评论74阅读模式
英文:

How to Implement Angular Auth Guard

问题

我正在构建一个Angular应用程序。在这个应用程序中,我使用了身份验证守卫(Auth Guard)来保护应用程序。我是这样添加身份验证守卫的。

{ path: 'order', component: OrderComponent, canActivate: [AuthGuard]}

当我点击“Order”按钮时,如果用户未经身份验证,应该被重定向到登录页面。用户输入凭据后,应该重定向到“order”页面。

这是我的身份验证守卫实现。

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    let isLoggedIn = this.authService.isAuthenticated();
    if (isLoggedIn) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

这是我的身份验证服务实现。

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  redirectUrl: string;
  isLoggedIn = false;

  constructor(private router: Router) {}

  isAuthenticated() {
    this.redirectUrl = this.router.url;
    return this.isLoggedIn;
  }
}

这是我的登录身份验证实现。

onClickSubmit() {
    const headers = new HttpHeaders({authorization: 'Basic ' + window.btoa(this.loginData.email + ":" + this.loginData.password)});
    this.httpClient.get("http://localhost:8181/authorize/", { headers, responseType: 'text' as 'json' })
      .subscribe(
        (response) => {
          console.log(response);
          this.router.navigate([this.authService.redirectUrl || '/order']);
        },
        (error) => console.log(error)
      );
 }

尽管如此,我仍然无法正确实现我的需求。

需求 - 当我点击“Order”按钮时,如果用户未经身份验证,应该被重定向到登录页面。用户输入凭据后,应该重定向到“order”页面。

英文:

I am building an Angular application. In this application, I used Auth Guard to secure the application. I added the Auth guard in the following way.

  { path:'order', component: OrderComponent, canActivate: [AuthGuard]}

When I click on Order If the user is not authenticated he should route to the login page. After the user enters his credentials user should redirect to the 'order' page.

Here is my Auth Guard implementation.

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private authService:AuthService, private router: Router, state: RouterStateSnapshot){};
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
    let isLoggedIn = this.authService.isAuthenticated();
    if (isLoggedIn){
      return true
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
  
}

And here is my Auth Service implementation.

import { Router } from '@angular/router';
@Injectable({
  providedIn: 'root'
})
export class AuthService {

  redirectUrl: string;
  isLoggedIn = false;
  constructor(private router: Router) { }
isAuthenticated(){
  this.redirectUrl = this.router.url;
    return this.isLoggedIn;
  }
}

And here is my login AUthentication implementation.

    const headers= new HttpHeaders({authorization: 'Basic ' +window.btoa(this.loginData.email+":"+this.loginData.password)});
    this.httpClient.get("http://localhost:8181/authorize/", {headers, responseType : 'text' as 'json'})
    .subscribe(
      (response) => {console.log(response);
        this.router.navigate([this.authService.redirectUrl || '/order']);},
      (error) => console.log(error));

    
 }

Still, I was unable to properly implement my requirement.

Requirement - When I click on the Order button If the user is not authenticated he should route to the login page. After the user enters his credentials user should redirect to the 'order' page.

答案1

得分: 2

You can save original URL requested by the user in returnUrl

Auth Guard

this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});

Then use the returnUrl to navigate after login success

Auth Service

const returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
this.router.navigateByUrl(returnUrl);

Refer here: https://jasonwatmore.com/post/2022/12/01/angular-14-redirect-to-previous-url-after-login-with-auth-guard#:~:text=Angular%20Auth%20Guard&text=The%20auth%20guard%20uses%20the,returnUrl%20in%20the%20query%20parameters.

英文:

You can save original URL requested by the user in returnUrl

Auth Guard

this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});

Then use the returnUrl to navigate after login success

Auth Service

      const returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
      this.router.navigateByUrl(returnUrl);

Refer here: https://jasonwatmore.com/post/2022/12/01/angular-14-redirect-to-previous-url-after-login-with-auth-guard#:~:text=Angular%20Auth%20Guard&text=The%20auth%20guard%20uses%20the,returnUrl%20in%20the%20query%20parameters.

答案2

得分: 2

Login API Service返回Observable,因为http响应始终是异步的。这里不需要订阅!

isAuthenticated(): Observable<boolean> {
  return this.httpClient.get("你的身份验证URL").pipe(
    /* 运算符 - map,catchError - 根据需要 */
  )   
}

canActivate返回Observable给Router。Router在内部进行订阅,你不需要手动订阅。

export class AuthGuard implements CanActivate {
  constructor(
    private authService: AuthService,
    private router: Router,
  ){};
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot) {
     return this.authService.isAuthenticated().pipe(
       map(auth => auth || this.router.parseUrl('/login')),
     )
  }
}

登录后,你可以在Login组件中重定向到/order。你可以在某个服务中保存返回路径,或将其附加到/login路径作为参数。

英文:

Login API Service returns Observable, because http responses are always asynchronous. No subscription here!

isAuthenticated(): Observable&lt;boolean&gt; {
 return this.httpClient.get(&quot;your auth url&quot;).pipe(
   /* operators - map, catchError - as needed */
 )   
}

canActivate returns Observable to Router. Router internally subscribes, You don't need to subscribe.

export class AuthGuard implements CanActivate {
  constructor(
    private authService:AuthService,
    private router: Router,
  ){};
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot) {
     return this.authService.isAuthenticated().pipe(
       map(auth =&gt; auth || this.router.parseUrl(&#39;/login&#39;)),
     )
  }
}

After login you can redirect to /order in Login component. You can save return path in some service or append to /login path as parameter.

huangapple
  • 本文由 发表于 2023年3月7日 15:08:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75658903.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定