【问题标题】:Equivalent to route guards for component functions相当于组件功能的路由保护
【发布时间】:2018-04-15 12:12:33
【问题描述】:

我想知道是否存在与角度组件功能(特别是单击事件)的路由保护等效的方法。

我们设置了一个路由守卫,在未登录时会打开一个登录页面。这很好用。问题是,我们有一个不需要身份验证即可查看的组件,但组件中的某些功能确实需要身份验证。例如,新闻文章列表,但upvote/downvote 按钮需要身份验证才能使用。

upvote/downvote 按钮只是触发组件功能的点击事件。我们可以将我们在自定义路由保护中使用的逻辑添加到这些函数中,但这会导致大量重复代码。

我想知道 Angular 是否有内置的东西可以解决这个问题。我正在考虑类似于 ASP.NET MVC 的 [Authorize] 属性的东西,您可以将其放在操作的顶部进行身份验证。据我所知,路由守卫仅适用于路由,而不适用于点击事件。

【问题讨论】:

  • 没有什么比功能守卫更好的了,但我相信你有某种 auth.service,你可以在点击时检查 authService.isAuthorized()。此处保护的另一种方法是完全使用 *ngIf 将这些按钮从 DOM 中隐藏起来,再次引用组件中的某个布尔值,您可以在 ngOnInit 中设置这些布尔值。如果您需要动态跟踪 isAuthorized 您可以将事件发射器或主题放在您的 authService 中,这将传播更改并订阅它。

标签: angular angular4-router


【解决方案1】:

我找到了另一种实现动作防护的方法。它是拦截器。 当操作在没有有效令牌或没有必要数据的情况下向服务器发送请求时,服务器返回 401 或 403,具体取决于您的设置

@Injectable()
export class HttpAuthInterceptor {
  constructor(
    private toasterService: ToasterService,
    private auth: AuthService,
    private dialog: MatDialog) { }

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

    request = request.clone({
      setHeaders: {
        'Authorization': `Bearer ${this.auth.token}`
      }
    });

    return next.handle(request)
      .pipe(catchError(error => {
        if (error instanceof HttpErrorResponse) {
          switch (error.status) {
            case 401:
              this.auth.logout(request.urlWithParams);
              this.dialog.closeAll();
              break;
            case 403:
              this.dialog.closeAll();

              this.dialog.open(ConfirmDialogComponent, {
              
                autoFocus: false,
                width: '65rem',
                maxHeight: '95vh',
                maxWidth: '80vw',
                panelClass: 'confirme__dialog',
                data: {
                  title: 'CONFIRM_DIALOG.TITLE',
                  text: 'CONFIRM_DIALOG.TEXT',
                  onConfirm: () => {
                    this.auth.logout(request.urlWithParams)
                  }
                }
              });

              break;
            case 0:
              this.toasterService.error(error.message, {
                duration: 5000,
              });
              break;
            default:
              this.toasterService.error(error.error.Message, {
                duration: 5000,
              });
          }
        }

        return throwError(error);
      }));

  }
}

【讨论】:

    【解决方案2】:

    对于任何对解决方案感兴趣的人,我能够弄清楚如何在函数中使用我现有的路由保护。这消除了 if/else 语句的需要,其中 else 语句包括路由保护在未经身份验证时执行的逻辑。似乎是我能找到的最干净的解决方案。

    constructor(private authGuard: AuthGuard, private route: ActivatedRoute){}
    
    upvoteClick(article: NewsArticle): void {
    
        if (this.authGuard.canActivate(this.route.snapshot)) {
            //logic requiring authentication
        } 
        
    }

    【讨论】:

      【解决方案3】:

      如果您的用户已登录,您的路由守卫如何测试?希望您已经设置了一个授权服务来检查它并将其注入您的警卫。如果是这样,请将其注入您的投票组件并简单地使用 *ngIf 根据用户是否登录来隐藏/显示投票按钮。

      【讨论】:

      • 是的,我有一个可以注入的服务来确定用户是否经过身份验证(与我在路由保护中使用的相同)。我想我的问题是我不想隐藏按钮,我希望它们仍然进入点击侦听器功能,但如果未通过身份验证则提示登录窗口。我可以做到所有这些,但我希望有一种方法可以避免在我想要使用包含重定向到登录窗口的 else 进行身份验证的每个函数中使用 if/else 语句。但如果这是我需要做的,那就是我需要做的!
      猜你喜欢
      • 1970-01-01
      • 2018-01-28
      • 2022-11-16
      • 2020-08-09
      • 2016-02-02
      • 2011-12-06
      • 2021-10-27
      • 2021-01-10
      • 1970-01-01
      相关资源
      最近更新 更多