我实际上是在尝试准确了解所有应该如何工作,实际上,身份验证的逻辑是这样的。
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 中处理身份验证的提示。
Angular 附带的一些我关注这个主题的工具是:APP_INITIALIZER (an article 上 - 因为文档很少),HttpInterceptor , LoadingComponent 或只是典型的 AppComponent。
在此过程中也对我有帮助的一些依赖项是 ngx-store和 ngxs 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 token 注入(inject)了 cookie 名称。我发现它更清晰并坚持 Angular 原则:
export const JWT_COOKIE_NAME = new InjectionToken<string>('ACTUAL_JWT_COOKIE_NAME');
在上述情况下,如果您通过 cookie(不是身份验证 header )传递 JWT token 。
如果您确实传递了带有 token 的 header ,则可以执行诸如拦截 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 初始化程序可以执行诸如分派(dispatch)登录操作之类的操作 - 或者实际上直接调用身份验证服务方法(我喜欢使用 ngxs 商店来处理此类事情):
export function appRun(store: Store) {
return () =>
store
.dispatch(new Login())
.pipe(finalize(() => true)) // let the app handle errors after bootstrapped
.toPromise();
}
在 Loading Component 或 App Component 中有这样的东西:
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()))
);
}
你可以继承一个 guard 服务:
@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();
}
}
关于angular - Angular 7 和 CAS 身份验证的提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55647589/