【问题标题】:How can I redirect a user if they are not authenticated using router如果用户未使用路由器进行身份验证,如何重定向用户
【发布时间】:2018-06-26 00:15:31
【问题描述】:

在 Angular 2 中,如果用户未使用路由器版本 2.0.0-rc.1 进行身份验证,我如何重定向用户

我希望在存储路线的 app.component 中执行此操作。

我想检测用户在访问页面组件之前是否已通过身份验证。 所以我可以将它们重定向到登录。

我尝试了 canActivate,这似乎不适用于我的路由器版本。

我正在为这个版本的路由器寻找解决方案:"@angular/router": "2.0.0-rc.1"

最新版本路由器的解决方案。如果提供了,你能告诉我如何使用 git bash 和这个解决方案更新我的路由器版本。

这是我当前的代码:

export class AppComponent implements CanActivate {
    authService: AuthService;
    userService: UserService;

    constructor(_authService: AuthService, _userService: UserService, private location: Location, private router: Router) {
        this.authService = _authService;
        this.userService = _userService;
    }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable < boolean > | boolean {

        //This doesnt get hit
        console.log("here");

        return true;
    }
}

【问题讨论】:

  • John Papa 在这里有一个很好的使用 CanActivate/CanDeactivate 的例子:github.com/johnpapa/event-view。虽然,他使用的是 RC4。
  • 更新路由器节点模块的 git bash 命令是什么?对于 rc4
  • 理想情况下我想使用我当前的路由器版本
  • 2.0.0 路由器已弃用。您不想使用 3.0.0,因为那是 Angular 2 的最新版本吗? (3.0.0-beta.2 可能真的可以工作)
  • 可能,是的,任何与路由器相关的东西。这可能会产生很大的影响。我进行了过渡踢和战斗,但这是值得的。 :)

标签: angular angular2-routing


【解决方案1】:

使用Interceptor

import {bootstrap} from '@angular/platform-browser-dynamic';
import {provide} from '@angular/core';
import {HTTP_PROVIDERS, Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers} from '@angular/http';
import {ROUTER_PROVIDERS, Router} from '@angular/router';
import {LocationStrategy, HashLocationStrategy} from '@angular/common';
import { Observable } from 'rxjs/Observable';
import * as _ from 'lodash'

import {MyApp} from './app/my-app';

class HttpInterceptor extends Http {

    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router) {
        super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.request(url, options));
    }

    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.get(url,options));
    }

    post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {   
        return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
    }

    put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
    }

    delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.delete(url, options));
    }

    getRequestOptionArgs(options?: RequestOptionsArgs) : RequestOptionsArgs {
        if (options == null) {
            options = new RequestOptions();
        }
        if (options.headers == null) {
            options.headers = new Headers();
        }
        options.headers.append('Content-Type', 'application/json');
        return options;
    }

    intercept(observable: Observable<Response>): Observable<Response> {
        return observable.catch((err, source) => {
            if (err.status  == 401 && !_.endsWith(err.url, 'api/auth/login')) {
                this._router.navigate(['/login']);
                return Observable.empty();
            } else {
                return Observable.throw(err);
            }
        });

    }
}

bootstrap(MyApp, [
  HTTP_PROVIDERS,
    ROUTER_PROVIDERS,
    provide(LocationStrategy, { useClass: HashLocationStrategy }),
    provide(Http, {
        useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions, router: Router) => new HttpInterceptor(xhrBackend, requestOptions, router),
        deps: [XHRBackend, RequestOptions, Router]
    })
])
.catch(err => console.error(err));

【讨论】:

  • 我正在寻找一种解决方案来添加到我的路线所在的 app.component 文件中。我想在路由到达页面组件之前捕获它,这样如果它们没有经过身份验证,我可以将它们重定向到登录页面
  • 我很惊讶这是答案,因为它的代码比在 Angular 1 中解决相同问题的代码多 4-5 倍。
  • 你可以只覆盖 get 方法
  • 当我尝试使用 useFactory 在拦截器中注入路由器时,在 ./~/@angular/Router/@angular/router.es5.js 中出现以下异常 ARNING 有多个模块的名称不同在外壳中。在使用其他大小写语义的文件系统上编译时,这可能会导致意外行为。使用相等的大小写。比较这些模块标识符: node_modules\@angular\Router\@angular\router.es5.js 由 1 个模块使用,i。 e. …………
【解决方案2】:

你可以用这个

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Router } from '@angular/router';

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {

  constructor(private router: Router) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req)
      .pipe(
        catchError(
          (err: HttpErrorResponse) => {
            if (this.router.url !== '/login' && err.status === 401) {
              this.router.navigate(['/login']);
            }
            return throwError(err);
          }
        )
      );
  }

}

在 app.module.ts 中

{
  provide: HTTP_INTERCEPTORS,
  useClass: ErrorInterceptor,
  multi: true,
},

【讨论】:

    猜你喜欢
    • 2021-06-19
    • 2017-07-31
    • 2018-01-06
    • 2017-09-11
    • 2021-10-11
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    相关资源
    最近更新 更多