在Angular中使用JWT认证方法示例(2)

不过要注意,因为荷载是base64编码,这种编码可以对称解密,所以在荷载中不应该存放用户的敏感信息,比如密码。所以一般JWT用来向Web传递一些非敏感信息,例如用户名、所属部门等。

在Angular中使用JWT

这里我们以Angular6和koa2(使用TypeScript)为例,介绍一下如何在你的Angular应用中使用JWT。

服务端

首先在jwt.io 官网上找到node的JWT的库: jsonwebtoken

在Angular中使用JWT认证方法示例

可以看到官网把这个库对标准注册声明字段的支持情况以及加密方式的支持情况都列出来了。除了这个库,还需要使用koa一个中间件: koa-jwt ,用来对HTTP请求进行JWT认证。你可以通过下面命令安装这两个库:

npm i koa-jwt jsonwebtoken --save

在 app.ts 中:

import * as jwt from 'koa-jwt'; app.use(jwt({ secret: Secret }).unless({ path: [/\/register/, /\/login/, /\/groups/], }));

这里的secret就是你自己定义的秘钥, unless 方法用来排除一些不需要进行JWT认证的api。koa-jwt中间件需要放在路由中间件之前,这样就可以对所有路由(除了 unless 中设置的路由外)进行JWT的检查。只有正确之后才能正确的访问。

除此之外,你还要自定义一个401错误处理的中间件,如果没有token,或者token失效,该中间件会给出对应的错误信息。如果没有自定义中间件的话,会直接将 koa-jwt 暴露的错误信息直接返回给用户。

export const errorHandle = (ctx, next) => { return next().catch((err) => { if (err.status === 401) { ctx.status = 401; handleError({ctx, message: '登录过期,请重新登录', err: err.originalError ? err.originalError.message : err.message}); } else { throw err; } }); };

然后把这个中间件放在koa-jwt之前:

app.use(errorHandle); app.use(jwt({ secret: Secret }).unless({ path: [/\/register/, /\/login/, /\/groups/], }));

在用户登陆时候,生成token,返回给客户端:

// 生成 token 返回给客户端 const token = jsonwebtoken.sign({ user: { workNumber: user.workNumber, realName: user.realName, group: user.group, role: user.role }, // 设置 token 过期时间 exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24), // 1天 }, Secret); handleSuccess({ ctx, message: '登陆成功!', response: { token, lifeTime: Math.floor(Date.now() / 1000) + (60 * 60 * 24) // 1天 } });

需要注意的是,在使用 jsonwebtoken.sign() 时,需要传入的 secret 参数,这里的 secret 必须要与 前面设置 jwt() 中的 secret 一致。

客户端

在Angular中,我们需要使用 @auth0/angular2-jwt 这个库来帮助我们在Angular中处理JWT:

npm install @auth0/angular-jwt --save

在 app.module.ts 中引入 JwtModule 这个模块(注意,引入该模块的同时也要引入 HttpClientModule 模块):

import { JwtModule } from '@auth0/angular-jwt'; import { HttpClientModule } from '@angular/common/http'; export function tokenGetter(){ return localStorage.getItem('token'); } @NgModule({ bootstrap: [AppComponent], imports: [ // ... HttpClientModule, JwtModule.forRoot({ config: { tokenGetter: tokenGetter, whitelistedDomains: ['localhost:3001'], blacklistedRoutes: ['localhost:3001/auth/'] } }) ] }) export class AppModule {}

在 JwtModule 的 config 中:

tokenGetter :从localStorage中获取token;

whitelistedDomains :允许发送认证的请求的域名;

blacklistedRoutes :你不希望替换header中 Authorization 信息的api列表。

接着创建一个全局的 auth.service.ts 服务,方便在登陆的时候获取用户相关信息及权限,这个服务中有个 login 方法,用来处理登陆后返回的token信息,并把token存到LocalStorage中,这样在token失效前,下次用户登陆时就不需要输入用户名和密码:

login(loginInfo: LoginInfo): Observable<boolean> { return this.passportService.postLogin(loginInfo).pipe(map( (res: LoginRes) => { // 登陆成功后获取token,并存到localStorage this.storageService.setLocalStorage('token', res.token); const decodedUser = this.decodeUserFromToken(res.token); this.setCurrentUser(decodedUser); this.msg.success('登录成功!'); return this.loggedIn; } ) ); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/65aff1bf3488e37ed4b7c0d02a1f3b90.html