【问题标题】:Redirect If Token Not Valid令牌无效时重定向
【发布时间】:2017-02-25 12:56:25
【问题描述】:

我正在使用 Angular2 和 Auth0 进行身份验证。我可以看到令牌正在存储到本地存储中。我正在我的 auth.service.ts 文件中编写一个函数来检查一个有效的令牌,然后在组件的 init 上调用该函数。我尝试了此功能的许多不同变体,但无法让应用程序正确验证。

登录后,即使我登录并检索到有效令牌,它也会将我转发回主页。

我的目标是不允许在没有有效令牌的情况下访问此页面。但是当有一个有效的令牌时允许访问这个页面。

这是我目前尝试过的,

auth.service.ts

import { Injectable }                      from '@angular/core';
import { Router, CanActivate }             from '@angular/router';
import { tokenNotExpired, JwtHelper }      from 'angular2-jwt';
import { myConfig }                        from './auth.config';

// Avoid name not found warnings
declare var Auth0Lock: any;

var options = {
    theme: {
    logo: '../assets/img/logo.png',
    primaryColor: '#779476'
    },
    auth: {
    responseType: 'token',
    redirect: true,
    redirectUrl: "http://localhost:3000/dashboard",
    },
    languageDictionary: {
    emailInputPlaceholder: "email@example.com",
    title: "Login or SignUp"
  }, 
 };

@Injectable()
export class Auth {

  // Configure Auth0
  lock = new Auth0Lock(myConfig.clientID, myConfig.domain, options,{});

  constructor(private router: Router ) {
    // Add callback for lock `authenticated` event
    this.lock.on('authenticated', (authResult) => {
      localStorage.setItem('jwtToken', authResult.idToken);
    });
  }

   public login() {
    this.lock.show();
  };

  public authenticated() {
    return tokenNotExpired();
  };

  public isAuthenticated(): boolean {
    try {
        var jwtHelper: JwtHelper = new JwtHelper();
        var token = this.accessToken;
        if (jwtHelper.isTokenExpired(token))
            return false;
        return true;
    }
    catch (err) {
        return false;
    }
  }

  private get accessToken(): string {
        return localStorage.getItem('jwtToken');
    }

  public logout() {
    localStorage.removeItem('jwtToken');
  };
}

guard.service.ts

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

@Injectable()
export class Guard implements CanActivate {

    constructor(protected router: Router, protected auth: Auth ) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
        if (state.url !== '/pages/home' && !this.auth.isAuthenticated()) {
            this.auth.logout();
            this.router.navigate(['/pages/home']);
            return false;
        }
        return true;
    }
}

app.routing.ts

import {Guard}                          from "./services/guard.service";

const appRoutes: Routes = [
    {
        path: '',
        redirectTo: 'pages/home',
        pathMatch: 'full',
    },
    {
        path: '',
        component: FullLayoutComponent,
        canActivate: [Guard],
        data: {
            title: 'Home'
        },
        children: [
            {
                path: 'dashboard',
                component: DashboardComponent,
                data: {
                    title: 'Dashboard'
                }
            },

app.module.ts

import { Guard }                        from "./services/guard.service";
import { Auth }                         from "./services/auth.service";

providers: [ 
    Guard,
    Auth 
    ],

【问题讨论】:

    标签: javascript angular typescript auth0


    【解决方案1】:

    使用Guards的正确方法

        import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
    import { AuthService } from './authService';
    import { Observable } from 'rxjs/Observable';
    
    @Injectable()
    export class AuthGuard implements CanActivate {
    
        constructor(protected router: Router, protected authService: AuthService) {
    
        }
    
        canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
    
            if (state.url !== '/login' && !this.authService.isAuthenticated()) {
                this.authService.logOut();
                this.router.navigate(['/login']);
                return false;
            }
    
            return true;
        }
    }
    

    还有你的死记硬背

     path: 'admin',
            component: AdminPages.AdminPagesComponent,
            canActivate: [AuthGuard],
            children: [
                {
                    path: 'dashboard',
                    component: Dashboard,
                    data: {
                        menu: {
                            title: 'Dashboard',
                            icon: 'ion-android-home',
                            selected: false,
                            expanded: false,
                            order: 0
                        }
                    }
                },
    

    认证服务

    public isAuthenticated(): boolean {
        try {
            var jwtHelper: JwtHelper = new JwtHelper();
            var token = this.accessToken;
            if (jwtHelper.isTokenExpired(token))
                return false;
            return true;
        }
        catch (err) {
            return false;
        }
    }
    
    public logOut(): void {
        localStorage.removeItem("access_token");
    }
    
    private get accessToken(): string {
            return localStorage.getItem('access_token');
        }
    
    
    
     private saveJwt(jwt): void {
            if (jwt) {
                localStorage.setItem('access_token', jwt)
            }        
        }
        public login(loginModel: LoginModel): Promise<void> {
            return new Promise<void>((resolve, reject) => {
                var username = loginModel.email;
                var password = loginModel.password;
                var creds =
                    "username=" + username + "&password=" + password + "&client_id=" + this.clientId + "&grant_type=" + this.grant_type;
                var headers = new Headers();
                headers.append('Content-Type', 'application/x-www-form-urlencoded');
                this.httpClient.post(this.identityServerUrl + "/connect/token", creds, { headers })
                    .toPromise()
                    .then(response => {
                        this.saveJwt(response.json().access_token);
                        resolve();
                    })
                    .catch(err => {
                        reject(err.json().error_description)
                    });
            });
        }
    

    【讨论】:

    • 感谢您的帮助。我试图通过这个来了解发生了什么。我假设一旦我把它放在正确的地方,我需要导入一些东西,this.accessToken 是 auth0 的内置对象吗?
    • @wuno 在当前示例中我将 angular2-jwt 用于 jwtHelper,您能否提供您将哪个库用于 tokenNotExpired 函数?
    • 我正在使用这个 import { tokenNotExpired } from 'angular2-jwt';在我的 auth.service.ts
    • 所以它现在可以工作了。当我没有登录就进入仪表板时,它会将我转发回主页。但是当我登录时,JWT 没有被存储到 localStorage 中。我没有更改任何内容,只是添加了您提供的代码。您能想到导致我的令牌不被存储的任何原因吗?
    • 您需要存储令牌,我刚刚提供了我的情况。查看 login 和 savejwt 方法
    猜你喜欢
    • 2021-02-14
    • 2020-09-19
    • 2019-03-19
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 2016-06-14
    相关资源
    最近更新 更多