【问题标题】:Tips for Angular 7 and CAS authentication?Angular 7 和 CAS 身份验证的提示?
【发布时间】:2019-04-12 08:35:59
【问题描述】:

我实际上是想弄清楚所有应该如何工作,实际上,身份验证的逻辑是这样的。

1) 用户进入 Angular 应用程序,单击登录并重定向到可以使用这样的 URL 模式登录,并将我的 Angular 应用程序作为参数: cas-example.com/login?service=my-angular-app

2) 如果用户在 URL 中使用服务票证登录 cas 重定向到 Angular 应用程序,应该是这样的:my-angular-app.com/?ticket=ST-1232431

3) 在我应该将票证发送到我的后端并且如果票证有效时,后端会向我发送一个 jwt,我可以在其中登录用户

这种方法好吗?我应该如何从票证中实现监听器,我应该检查重定向是否来自 cas 并检查 URL,还是总是检查 URL?

这是cas的流程图:

【问题讨论】:

    标签: angular authentication cas


    【解决方案1】:

    具体来说有点困难,但我会尝试为您提供一些关于如何在 Angular 中处理身份验证的提示。

    Angular 附带的一些我关注这个主题的工具是:APP_INITIALIZER(上面有an article - 因为文档很少)、HttpInterceptor、LoadingComponent 或只是典型的 AppComponent。

    在此过程中对我也有帮助的一些依赖项是 ngx-storengxs store。尽管名称相似,但它们是不同的工具。

    我不会给你一个完整的回答你的问题,但一些提示:

    例如,在身份验证服务中,您可以注册一个回调来监听某个正在修改的 cookie(感谢 ngx -store)。像这样:

    constructor(public cookiesStorageService: CookiesStorageService,
              @Inject(JWT_COOKIE_NAME) private _JWT_COOKIE_NAME: string) {
    this.cookiesStorageService
      .observe(this._JWT_COOKIE_NAME)
      .subscribe((cookie: NgxStorageEvent) => this.checkIfNewToken(cookie.newValue));
    

    }

    请注意,上面为 JWT 令牌注入了 cookie 名称。我发现它更清晰并坚持角度原则:

    export const JWT_COOKIE_NAME = new InjectionToken<string>('ACTUAL_JWT_COOKIE_NAME');
    

    在上述情况下,如果您通过 cookie(不是身份验证标头)传递 JWT 令牌。 如果您确实传递了带有令牌的标头,则可以执行诸如拦截 HTTP 请求之类的操作。类似的东西:

    @Injectable()
    export class AuthenticationInterceptor implements HttpInterceptor {
    
        constructor(private tokenExtractor: HttpXsrfTokenExtractor,
              private authService: AuthenticationService,
              @Inject(API_ENDPOINT) private _API_ENDPOINT: string) {
        }
    
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
        if (req.url.match(this._API_ENDPOINT)) {
            // this.authService.intercept$.next(req);
    
            const XSRFTokenHeaderName = 'X-XSRF-TOKEN';
            const XSRFToken = this.tokenExtractor.getToken() as string;
            if (XSRFToken !== null && !req.headers.has(XSRFTokenHeaderName)) {
              req = req.clone({headers: req.headers.set(XSRFTokenHeaderName, XSRFToken)});
            }
    
            req = req.clone();
    
            return next.handle(req);
          } else {
            return next.handle(req).map(event => {
              if (event instanceof HttpResponse) {
                  // do something with response like sending it to an authentication service
              }         
              return event;
          });
          }
        }
      }
    

    我留下处理 X-XSRF-TOKEN 的规范示例。

    App 初始化程序可以执行诸如调度登录操作之类的操作 - 或者实际上直接调用身份验证服务方法(我喜欢使用 ngxs 存储来处理这类事情):

    export function appRun(store: Store) {
      return () =>
        store
          .dispatch(new Login())
          .pipe(finalize(() => true)) // let the app handle errors after bootstrapped
          .toPromise();
        }
    

    在加载组件或应用程序组件中有这样的东西:

    constructor(
        private router: Router,
        private actions$: Actions
    ) {}
    
    ngOnInit() {
    
        this.actions$
          .pipe(ofActionErrored(Login))
          .subscribe(() => this.router.navigate([Routes.PUBLIC]));
    
        this.actions$
          .pipe(ofActionSuccessful(Logout))
          .subscribe(() => this.router.navigate([Routes.PUBLIC]));
     }
    

    NGXS 附带了操作成功或错误操作的有用处理程序,您可以使用这些处理程序在某处路由(上述路由在枚举中定义)。

    因此,我在此响应中留下了许多步骤(例如声明状态、注册 APP_INITIALIZER、拦截器,...),但如果您认为评论有助于了解更多信息,请随意。 提到的库非常强大,可以帮助您以不同的方式解决问题(或者最终可能只是开销 - 只是一个存储某些状态的服务和一个拦截器可能就足够了)。 这不是很具体,但我认为这是一组很好的提示,可以帮助您继续前进。

    编辑:我忘记了路线守卫。它们还可以帮助在 Angular 中进行身份验证。 CanLoad(用于延迟加载的模块)和 CanActivate 尤其是守卫。类似的东西:

    canActivateRead(): Observable<boolean> | boolean {
        const perm = this.store.selectSnapshot(state => state.module.acl);
        if (perm) {
          return this.canRead(perm);
        } else {
          return this.fetchACLAndTestPermission('READ');
        }
    }
    
    private fetchACLAndTestPermission(perm: 'READ' | 'CREATE' | 'UPDATE'): Observable<boolean> {
        return this.authService.getPermissionForACL('ACL').pipe(
          tap(permission => this.store.dispatch(new SetMainACL({ permission }))),
          map(perm => this.canRead(perm)),
          tap(isPermitted => (isPermitted ? isPermitted : this.feedback.notAllowed()))
    );
    

    }

    你可以继承到一个守卫服务:

    @Injectable({
      providedIn: 'root'
    })
    export class ParameterBaseGuard extends ParameterGuards implements CanLoad {
      constructor(public authService: AuthenticationService, public feedback: FeedbackService, public store: Store) {
        super(authService, feedback, store);
      }
      canLoad(): Observable<boolean> | Promise<boolean> | boolean {
        return this.fetchACLAndTestPermission('READ');
      }
      canActivate(): Observable<boolean> | Promise<boolean> | boolean {
        return this.canActivateRead();
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-05
      • 2019-03-10
      • 2021-02-17
      • 2011-08-07
      • 1970-01-01
      • 2020-01-06
      • 2019-07-04
      • 2021-03-22
      • 2018-04-15
      相关资源
      最近更新 更多