手机版

在Angular中使用JWT身份验证方法的示例

时间:2021-08-30 来源:互联网 编辑:宝哥软件园 浏览:

本文介绍了一个在Angular中使用JWT认证方法的例子,并与大家分享如下:

项目地址:分级系统

基于会话的身份验证和基于令牌的身份验证已广泛使用令牌。在会话认证中,服务器将存储用户登录信息,作为响应,该信息将被传输到浏览器,并保存为Cookie。在下一个请求中,这个登录信息将被带来,以便识别该请求来自哪个用户。

在基于会话的身份验证中,每个用户都应该生成一个会话,该会话通常存储在内存中。随着用户的增加,服务器的成本也会增加,对分布式应用不太友好。

在令牌认证中,服务器不需要保存用户认证信息。当用户登录时,服务器将在验证用户信息后返回一个令牌。这个令牌存储在客户端,这个令牌携带在每个请求的请求头中,这样服务器就可以在验证令牌后返回数据。

JWT(JSON Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,在各方之间以JSON对象的形式安全地传输信息。该信息可以通过数字签名进行验证和信任。特别适合分布式站点的单点登录(SSO)场景。

什么是JWT,为什么用JWT?

JWT是JSON网络令牌的缩写。这个问题最简单的答案就是JWT简单、紧凑、安全。具体来说:

简单性:只要用户登录,只需要添加一个http头身份验证信息就可以使用JWT身份验证,这可以简单地用一个函数来实现,我们将在下面的示例中看到。

Compact: JWT令牌是一个由base 64编码的字符串,它包含一些头信息和一些必要的数据,所以非常简单。带符号的JWT字符串通常不超过200字节。

安全性:JWT可以通过RSA或HMAC加密算法加密,确保令牌有效并防止篡改。

总之,您可以有一个安全有效的方法来验证用户,并验证所有api调用,而无需解析复杂的数据结构或实现您自己的加密算法。

JWT的组成

JWT由三部分组成,中间用。它们是:

标题(播放加载)签名(也就是说,JWT只是一个字符串,格式如下:

Header.payload.signature标头

标头通常由两部分组成:令牌的类型(即JWT)和使用的哈希算法,如HMAC SHA256或RSA。

然后,JSON被Base64编码以形成JWT的第一部分。

ewogichbgcoiaisfmyntyilacilj0exaiiaslduigp 9加载

JWT的第二部分是负载,其中包含声明。声明是关于实体(通常是用户)和其他数据的声明。陈述有三种:注册陈述、公开陈述和私人陈述。

JWT规范定义了在标准中注册的七个权利要求名称,它们是:

ISS:JWT发行人面临的用户aud sub:JWT:接收方JWT exp:JWT的到期时间,必须大于发行时间nbf:定义JWT不可用的时间。IAT:jwt的发行时间jti:jwt的唯一标识,主要作为一次性令牌,避免重放攻击。对于特定情况,您可以使用公共声明名称。其中包括:

Auth_time:身份验证发生的时间acr:身份验证上下文类的引用随机数:用于将客户端会话与标识令牌相关联的值。最后,还有私人索赔名称,可以用来传达与身份相关的信息,如姓名或部门。

由于公开和私人声明没有注册,请注意避免名称冲突。

例如,我们定义了一个palyload:

{'sub' :' 1234567890 ',' name' 3360' tc9011 ',' admin' : true,' exp' : 1441594722}然后用base64加密得到JWT :的第二部分

ewlogijzdwioiaimtizindu2nzg5 mcisciagim5 hbwioiaidgm5 dexiiwkicaiywratw4ioib0 cnvllaogiclehaioiaxndqxntk 0 nziycn 0=

签名

签名由base64编码的报头、base64编码的有效载荷和秘密组成。

例如,将上述两个编码的字符串用句点(head first)连接在一起形成:

ewogicjbgcioiiaisfmyntylalogij0 exaioiiaislidigp 9 . ewogicjzdwioiaimtizind2 nzg5 mcisciagim 5 hbwuiiaidgm5 dexiiwkicaiywratw4io IB 0 cnvllaogiclehaioiaxndqxntk 0 nziycn 0=

然后,上面拼接的字符串由HS256以secret作为密钥进行加密。

Hmacsha256 (base64 urlencode(标头)'.'base64 urlencode(有效载荷,秘密)使用JWT

通常,授权被添加到请求报头,并且承载被添加来标记它:

fetch ('API/v1/user/1 ',{ headers : { ' authorization ' 3360 ' carrier ' token } })服务器验证该令牌,如果验证通过,则返回相应的资源。

但是,应该注意的是,由于有效负载是base64代码,可以对称解密,因此用户的敏感信息(如密码)不应存储在有效负载中。因此,JWT一般用于向Web传递一些非敏感信息,如用户名、部门等。

在角形中使用JWT

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

计算机网络服务器

首先在jwt.io官网找到节点:jsonwebtoken的JWT图书馆。

可以看到官网列出了这个库对标准注册申报字段和加密方式的支持。除了这个库,您还需要使用koa中间件:koa-JWT,它用于HTTP请求的JWT认证。您可以使用以下命令安装这两个库:

NPM ikoa-jwt jsonwebtoken-保存在app.ts中:

从“koa-jwt”导入*作为jwt;app . use(jwt({ Secret 3360 Secret })。除非({ path: [/\/register/,/\/login/,/\/group/],});这里的秘密是您自己定义的密钥,除非方法用于排除一些不需要JWT身份验证的API。Koa-jwt中间件需要放在路由中间件之前,这样所有路由(除了在除非中设置的那些)都可以检查jwt。只有当它正确时,才能正确访问它。

此外,您需要为401错误处理定制一个中间件。如果没有令牌或者令牌无效,中间件会给出相应的错误信息。如果没有定制的中间件,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 3360 Secret })。除非({ path: [/\/register/,/\/login/,/\/group/],});当用户登录时,会生成一个令牌并将其返回给客户端:

//生成令牌并返回给客户端const token=jsonwebtoken . sign({ user : { work number 3360 user . work number,realname3360user.real name,group:user.group,Role: user.role },//设置令牌到期时间exp 3360 path . floor(date . now()/1000)(60 * 60 * 24),//1 day },Secret);Handlesuccess ({CTX,message: '登录成功!',response: {token,lifetime :数学。楼层(日期。now()/1000)(60 * 60 * 24)//1 day } });需要注意的是,在使用jsonwebtoken.sign()时,传入的secret参数是必需的,这里的secret必须与jwt()中的secret一致。

客户

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

npminstall @ auth0/angular-jwt-save在app.module.ts中引入了JwtModule(注意,除了这个模块之外,还应该引入HttpClientModule):

从" @auth0/angular-jwt "导入{ JwtModule };从" @angular/common/http "导入{ HttpClientModule };导出函数token getter(){ 0返回本地存储。getitem(' token ');} @ NgModule({ bootstrap :[AppComponent],imports: [ //.HttpClientModule,jwtmodule。for root({ config : { tokenGetter :token getter,白名单域3360 ['localhost:3001'],黑名单成员3360[' localhost :3001/auth/']})})导出类AppModule {}在JwtModule的配置中:

令牌获取器:从localStorage中获取令牌;

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

黑名单列表:你不希望替换页眉中批准信息的美国石油学会(美国石油协会)列表。

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

登录(LoginInfo : LoginInfo): Observableboolean {返回此。护照服务。登录后(登录信息).管道(地图)((RES : LoginRes)={//登陆成功后获取令牌,并存到本地存储。存储服务。setlocal storage(' token ',RES . token);const decodedUser=this。decodeuserfromtke(RES . token);这个。setcurrentuser(decodedUser);this.msg.success('登录成功!');返回this . loggedin }));}在这个注册方法中,decodeUserFromToken封装了@auth0/angular2-jwt中提供的decodeToken方法,注意decodeToken方法解析出来的只是服务端jsonwebtoken.sign()中的数据对象,所以需要通过。操作获取jsonwebtoken.sign()中定义的用户:

decodeUserFromToken(令牌):用户{返回这个。jwthelperservice。decodetoken(令牌)。用户;}在这个服务中,定义了两个变量登录和isAdmin,用来标识用户是否登录和其相应的权限,方便在有角的路由中控制可以访问的视图。

有登录当然就有登出,登出时只需把代币从LocalStorage中移除,并把几个变量重置即可:

注销():无效{ this。存储服务。remove local storage(' token ');this . loggedin=false this . isadmin=false this . currentuser=新用户();}AuthService的完整代码如下:

从“@棱角分明/核心”导入{可注射,注射器};从" @angular/router "导入{路由器};从" @auth0/angular-jwt "导入{ JwtHelperService };从“rjs”导入{可观察到};从“rxjs/运算符”导入{ map };从导入{登录信息,登录,用户}././view/passport/interfaces/passport ';从""导入{ PassportService }././视图/护照/服务/护照。“服务”;从导入{存储服务}./存储/存储。“服务”;从" ng-zorro-antd "导入{ NZmessageServiCe };@可注射()导出类AuthService { public loggedIn=false;public isAdmin=false公共货币:用户=新用户();构造函数(私有JwtHelperService : JwtHelperService,私有路由器:路由器,私有注射器:注射器,私有passport service : passport service,私有存储服务:存储服务){ const token=本地存储。getitem(' token ');if(token){ const decodedUser=this。decodeuserfromtoke(令牌);这个。setcurrentuser(decodedUser);} } get msg(): NzMessageService {返回此。注射器。get(NZmessageServiCe);}登录fo(LoginInfo : LoginInfo): Observableboolean {返回此。护照服务。登录后(登录信息).管道(地图)((RES : LoginRes)={ this。存储服务。setlocal storage(' token ',RES . token);const decodedUser=this。decodeuserfromtke(RES . token);这个。setcurrentuser(decodedUser);this.msg.success('登录成功!');返回this . loggedin }));}注销():无效{此。存储服务。删除本地存储(“令牌”);this . loggedin=false this . isadmin=false this . currentuser=新用户();} decodeUserFromToken(令牌):用户{返回这个。jwthelperservice。decodetoken(令牌)。用户;} setCurrentUser(decodedUser): void { this。loggedin=true这个。当前用户。工作编号=decodeduser。工作编号;这个。当前用户。真实姓名=decodeduser。实名;这个。当前用户。group=解码用户。团体;这个。当前用户。角色=解码用户。角色;这个。isadmin=decodeduser。角色10;删除decodedUser.role}}至此,在你的有角的应用中就引入了JWT认证,当然,你也可以不使用@auth0/angular2-jwt,自己手写一个超文本传送协议拦截器,手动设置每次请求的标题:

@可注射()导出类AuthInterceptor实现了Httpinterceptor { intercept(req : Httprequestany,next : Httphandler): observableHttpeventany { const token=本地存储。getitem(' token ');if(token){ const cloned=req。克隆({ headers : req。标题。set(' Authorization ',' border ' token)});返回next.handle(克隆的);} else {下一步返回。句柄(请求);} }}不过这样的话,令牌Base64解码也需要自己手写,稍微麻烦一点。

总结

JWT因为是基于数据的,所以通用性很强,很多语言已经存在智威汤逊广告公司相关的库。不过使用JWT的时候需要注意以下几点:

保存好秘密秘钥,这个秘钥只能在服务端存在给代币设置一个过期时间,因为一旦代币生成,它就永远有效,除非代币密钥被更改或过期在有效载荷中只能存储一些业务逻辑所必要的非敏感信息以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

版权声明:在Angular中使用JWT身份验证方法的示例是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。