日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JSON Web Tokens(JWT)

發(fā)布時(shí)間:2024/6/30 javascript 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JSON Web Tokens(JWT) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

現(xiàn)在API越來越流行,如何安全保護(hù)這些API? JSON Web Tokens(JWT)能提供基于JSON格式的安全認(rèn)證。它有以下特點(diǎn):

  • JWT是跨不同語言的,JWT可以在?.NET, Python, Node.js, Java, PHP, Ruby, Go, JavaScript和Haskell中使用
  • JWT是自我包涵的,它們包含了必要的所有信息,這就意味著JWT能夠傳遞關(guān)于它自己的基本信息,比如用戶信息和簽名等。
  • JWT傳遞是容易的,因?yàn)镴WT是自我包涵,它們能被完美用在HTTP頭部中,當(dāng)需要授權(quán)API時(shí),你只要通過URL一起傳送它既可。

JWT易于辨識(shí),是三段由小數(shù)點(diǎn)組成的字符串:

aaaaaaaaaa.bbbbbbbbbbb.cccccccccccc

這三部分含義分別是header,payload, signature

Header

頭部包含了兩個(gè)方面:類型和使用的哈希算法(如HMAC SHA256):

{ "typ": "JWT", "alg": "HS256" }

?

對(duì)這個(gè)JSON字符進(jìn)行base64encode編碼,我們就有了首個(gè)JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

JWT的第二部分是payload,也稱為?JWT Claims,這里放置的是我們需要傳輸?shù)男畔?#xff0c;有多個(gè)項(xiàng)目如注冊(cè)的claim名稱,公共claim名稱和私有claim名稱。

注冊(cè)claim名稱有下面幾個(gè)部分:

  • iss: token的發(fā)行者
  • sub: token的題目
  • aud: token的客戶
  • exp: 經(jīng)常使用的,以數(shù)字時(shí)間定義失效期,也就是當(dāng)前時(shí)間以后的某個(gè)時(shí)間本token失效。
  • nbf: 定義在此時(shí)間之前,JWT不會(huì)接受處理。開始生效時(shí)間
  • iat: JWT發(fā)布時(shí)間,能用于決定JWT年齡
  • jti: JWT唯一標(biāo)識(shí). 能用于防止 JWT重復(fù)使用,一次只用一個(gè)token;如果簽發(fā)的時(shí)候這個(gè)claim的值是“1”,驗(yàn)證的時(shí)候如果這個(gè)claim的值不是“1”就屬于驗(yàn)證失敗

?

公共claim名稱用于定義我們自己創(chuàng)造的信息,比如用戶信息和其他重要信息。

私有claim名稱用于發(fā)布者和消費(fèi)者都同意以私有的方式使用claim名稱。

下面是JWT的一個(gè)案例:

{ "iss": "scotch.io", "exp": 1300819380, "name": "Chris Sevilleja", "admin": true }

?

簽名

JWT第三部分最后是簽名,簽名由以下組件組成:

  • header
  • payload
  • 密鑰

下面是我們?nèi)绾蔚玫絁WT的第三部分:

var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload); HMACSHA256(encodedString, 'secret');

這里的secret是被服務(wù)器簽名,我們服務(wù)器能夠驗(yàn)證存在的token并簽名新的token。

?

TWT支持的算法有:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

============================================================================================================

以上是官網(wǎng)的理論部分,下面會(huì)有提供一些實(shí)例:

?首先 導(dǎo)入 依賴:

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.2.0</version> </dependency>

?1, 指定加密算法:

//HMAC Algorithm algorithmHS = Algorithm.HMAC256("secret");
-------------------------------------------------------------------------
//RSA

Map<String,Object> keys=RSAUtils.getKeys(); RSAPublicKey publicKey = (RSAPublicKey)keys.get("public"); //Get the key instance
RSAPrivateKey privateKey = (RSAPrivateKey)keys.get("private");//Get the key instance Algorithm algorithmRS = Algorithm.RSA256(publicKey, privateKey);

?2 , 生成token

? 用HS256生成token

try {Algorithm algorithm = Algorithm.HMAC256("secret");String token = JWT.create().withIssuer("auth0").sign(algorithm); } catch (UnsupportedEncodingException exception){//UTF-8 encoding not supported } catch (JWTCreationException exception){//Invalid Signing configuration / Couldn't convert Claims. }

? 用RS256生成token

Map<String,Object> keys=RSAUtils.getKeys();RSAPublicKey publicKey = (RSAPublicKey)keys.get("public"); //Get the key instanceRSAPrivateKey privateKey = (RSAPrivateKey)keys.get("private");//Get the key instance try {Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);String token = JWT.create().withIssuer("auth0").sign(algorithm); } catch (JWTCreationException exception){//Invalid Signing configuration / Couldn't convert Claims. }

? 3, 驗(yàn)證token

? ? 1)普通驗(yàn)證

? ? ? ?用HS256驗(yàn)證token

String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; try {Algorithm algorithm = Algorithm.HMAC256("secret");JWTVerifier verifier = JWT.require(algorithm).withIssuer("auth0").build(); //Reusable verifier instanceDecodedJWT jwt = verifier.verify(token); } catch (UnsupportedEncodingException exception){//UTF-8 encoding not supported } catch (JWTVerificationException exception){//Invalid signature/claims }

? ? ?用RS256驗(yàn)證token

String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; RSAPublicKey publicKey = //Get the key instance RSAPrivateKey privateKey = //Get the key instance try {Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);JWTVerifier verifier = JWT.require(algorithm).withIssuer("auth0").build(); //Reusable verifier instanceDecodedJWT jwt = verifier.verify(token); } catch (JWTVerificationException exception){//Invalid signature/claims }

? 2)在payLoad 是可以自定義數(shù)據(jù),用于驗(yàn)證,包括時(shí)間等。

? ? ?在生成token的時(shí)候指定數(shù)據(jù):

@Testpublic void gen1() throws IOException {String token ="";SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//日期轉(zhuǎn)字符串Calendar calendar = Calendar.getInstance();calendar.add(Calendar.SECOND,30 ); //特定時(shí)間的年后Date date = calendar.getTime();try {Algorithm algorithm = Algorithm.HMAC256("mysecrite");token = JWT.create().withIssuer("auth0").withSubject("xiaoming").withClaim("name", 123).withArrayClaim("array", new Integer[]{1, 2, 3}).withExpiresAt(date).sign(algorithm);System.out.println("loglogagel:"+token);} catch (UnsupportedEncodingException exception){//UTF-8 encoding not supported} catch (JWTCreationException exception){//Invalid Signing configuration / Couldn't convert Claims. }}

? ? 驗(yàn)證token是否過期,是否有制定的

@Testpublic void gen3(){String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhdXRoMCIsImV4cCI6MTQ5NzY4NTQwOX0.DHY-90JAA63_TvI-gRZ2oHCIItMajb45zB1tdCHQ_NQ";try {Algorithm algorithm = Algorithm.HMAC256("mysecrite");JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(algorithm).withIssuer("auth0").withSubject("xiaomong");Clock clock = new Clock() {@Overridepublic Date getToday() {return new Date();}};//Must implement Clock interfaceJWTVerifier verifier = verification.build(clock);DecodedJWT jwt = verifier.verify(token);System.out.println(jwt.getAlgorithm());System.out.println(jwt.getType());System.out.println(jwt.getIssuer());System.out.println(jwt.getExpiresAt());} catch (UnsupportedEncodingException exception){//UTF-8 encoding not supported exception.printStackTrace();} catch (JWTVerificationException exception){//Invalid signature/claims exception.printStackTrace();} }

如果 subject驗(yàn)證的不一致,就會(huì)報(bào)如下錯(cuò)誤:

??

如果時(shí)間超過 30 秒,會(huì)報(bào)如下錯(cuò)誤:

?對(duì)驗(yàn)證的方法稍加修改:

@Testpublic void gen3(){String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4aWFvbWluZyIsImFycmF5IjpbMSwyLDNdLCJpc3MiOiJhdXRoMCIsIm5hbWUiOiJJYW0gcmlnaHQgZnJvbSBjbGFpbSIsImV4cCI6MTQ5NzY4OTQ4NX0.6lsXISVAgi8B2wAvaZq4tj-h9Pgd6GGaOYZLz_gPFMU";try {Algorithm algorithm = Algorithm.HMAC256("mysecrite");JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(algorithm).withIssuer("auth0").withSubject("xiaoming");Clock clock = new Clock() {@Overridepublic Date getToday() {return new Date();}};//Must implement Clock interfaceJWTVerifier verifier = verification.build(clock);DecodedJWT jwt = verifier.verify(token);Map<String, Claim> claims = jwt.getClaims(); //Key is the Claim nameClaim claim = claims.get("name");System.out.println(claim.asString()); //打印出claim的值 System.out.println(jwt.getAlgorithm());System.out.println(jwt.getType());System.out.println(jwt.getIssuer());System.out.println(jwt.getExpiresAt());} catch (UnsupportedEncodingException exception){//UTF-8 encoding not supported exception.printStackTrace();} catch (JWTVerificationException exception){//Invalid signature/claims exception.printStackTrace();}

驗(yàn)證后的最后結(jié)果:

?

? ? ??

4,claim的添加,獲取

? ? 1) 內(nèi)置的payload主要有以下幾個(gè),如果沒有就返回null

? ? ?Issuer ("iss") :發(fā)布者

String issuer = jwt.getIssuer();

Subject ("sub")

String subject = jwt.getSubject();

Audience ("aud")

List<String> audience = jwt.getAudience();

Expiration Time ("exp")

Date expiresAt = jwt.getExpiresAt();

Not Before ("nbf")

Date notBefore = jwt.getNotBefore();

Issued At ("iat")

Date issuedAt = jwt.getIssuedAt();

JWT ID ("jti")

String id = jwt.getId();

?

?2)定義私有的claim

? ? 添加:

String token = JWT.create().withClaim("name", 123).withArrayClaim("array", new Integer[]{1, 2, 3}).sign(algorithm);

? ? 獲取:

JWTVerifier verifier = JWT.require(algorithm).withClaim("name", 123).withArrayClaim("array", 1, 2, 3).build(); DecodedJWT jwt = verifier.verify("my.jwt.token");

?目前,官方支持claim的類型的有:Boolean, Integer, Double, String, Date , String[] 和 Integer.

?

? 5, ?Header Claims

? ? ?1)header claims 是定義header部分的內(nèi)容,基本都是默認(rèn)定義,不需要自己去設(shè)置的,內(nèi)置的有:

Algorithm ("alg")

String algorithm = jwt.getAlgorithm();

Type ("typ")

String type = jwt.getType();

Content Type ("cty")

String contentType = jwt.getContentType();

Key Id ("kid")

String keyId = jwt.getKeyId();

?

? ? ? 2)添加:

Map<String, Object> headerClaims = new HashMap(); headerClaims.put("owner", "auth0"); String token = JWT.create().withHeader(headerClaims).sign(algorithm);

? ? ? 3)獲取:

Claim claim = jwt.getHeaderClaim("owner");

?

總結(jié): 看了其他人的一些博客,發(fā)現(xiàn)他們的api都是相對(duì)老一點(diǎn)的版本,生成token是一步一步來,新的確實(shí)簡(jiǎn)單方便很多。分享就這里,歡迎交流。

補(bǔ)充參考鏈接:

web 中使用jwt: ? ?https://github.com/jwtk/jjwt

?

參考地址:https://github.com/auth0/java-jwt

轉(zhuǎn)載于:https://www.cnblogs.com/minsons/p/7040753.html

總結(jié)

以上是生活随笔為你收集整理的JSON Web Tokens(JWT)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。