A、JWT導入
1. JWTは何ですか
JSONウェブトークン(JWT)は、ネットワークアプリケーション実行環境JSONベースの開発標準(RFC 7519)の間を通過するためには声明で、トークンは(特に着陸の単一のポイントに分散したサイトのため、コンパクトで安全であるように設計されてSSO)のシナリオ。JWTの文は、一般的に、サーバーからリソースを取得するために認証されたユーザID情報を提供するアイデンティティプロバイダとサービスプロバイダの間で使用されている、あなたはまた、いくつかの追加のビジネスロジックその他の必要な情報の声明、また、トークンを追加することができます直接認証に使用することができる暗号化されてもよいです。
2 ,,ベースのトークン認証メカニズム
HTTPプロトコルと同様に、ユーザの認証情報やセッション情報を保持するサーバを必要としないステートレストークンベースの認証機構です。アプリケーションがでているサーバーのユーザーログを検討する認証機構tokent機会を必要としないこと。このアプリケーションは便利な拡張機能を提供し、この手段
このようなプロセスがあります
- ユーザーは、ユーザー名とパスワードを使用してサーバに要求します
- ユーザー情報の認証用サーバー
- サーバーは、トークンを検証することにより、ユーザに送信します
- クライアントのストレージトークン、トークンと要求ごとの追加の値
- サーバー認証トークン、およびデータを返します。
このトークンはほかに、CORS(クロスオリジンリソースの共有)戦略をサポートするサーバは、我々は通常、アクセス制御、許可サーバーでそれを行う、それはリクエストヘッダに保つ必要があり、サーバーへの各要求とともに送信する必要があります-Origin:*
3、JWTの構成
JWTは、3つの部分から構成され、これら3つの情報はJWT文字列とのリンクを構成しています。このような
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
我々はコール負荷(平面上に担持アイテムに類似するペイロード)の第二の部分の頭部(ヘッダ)、および第三の部分を呼び出す最初の部分は、ビザ(署名)であります
ヘッダ
JWTヘッドによって運ばれる二つの情報:
- 宣言された型、ここにJWTがあります
- 暗号化アルゴリズムのアサーションは通常、HMAC SHA256直接使用されます
このように、次のJSONヘッドを完成
-
{
-
'typ':'JWT',
-
'alg':'HS256'
-
}
次に、ヘッドbase64で暗号化は、(暗号化は、対称復号化することができる)、第一の部分を構成します
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
plyload
ロードローカルストレージが有効な情報です。名前は、航空機上に担持されたそのような物品に特異的に指し、これらの効果的な情報は、3つの部分から構成され
- 標準的な登録届出書
- 公式声明
- Privateステートメント
登録マーク声明(必須使用を推奨しません)
- ISS:JWTの発行者
- サブ:ユーザーのためのJWT
- AUD:受信側JWT
- EXP:JWT有効期限、有効期限は、時間の問題よりも大きくなければなりません。
- NBF:JWTが使用できない前に何時間が定義されています
- IAT:時間の問題JWT
- JTI:JWT独自のアイデンティティ、主にリプレイ攻撃を避けるために、ワンタイムトークンとして使用されています
公共の声明:
公共の宣言は、必要な情報やその他のビジネスニーズを追加するために、ユーザーに関する一般的な情報を任意の情報を追加することができますが、クライアントの一部を復号化することができるので、機密性の高い情報を追加することを推奨していません。
Privateステートメント
BASE64は、情報の一部はテキスト情報の名に分類することができることを意味し、対称暗号化解除されるので、Privateステートメントは、消費者に定義された関数宣言のプロバイダであり、一般に機密情報を保存することは推奨されません。
ペイロードを定義します
-
{
-
"sub": "1234567890",
-
"name": "John Doe",
-
"admin": true
-
}
Base64では、取得した部分を暗号化しJWT
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
署名
第三の部分はJWTビザ情報であり、このビザ情報は、3つの部分からなります:
- (BASE64後)ヘッダ
- ペイロード(BASE64後)
- secred
この部分は、文字列を形成するように接続され、「」。BASE64ペイロードヘッダと暗号化された暗号BASE64を使用する必要があり、その後、組成物は、宣言された暗号化ヘッダが暗号化された秘密を追加して、第3の部分は、JWTを構成します
-
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
-
var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
完全な文字列にこれらの三つの部分との接続は、最終JWTを構成します「」:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
注:秘密は、サーバ側に保存されているJWTサービス側でも発行され、それはあなたのサーバの秘密鍵であるので、秘密は、JWTの発行とJWTを認証するために使用され、いずれかのシナリオに明らかにすべきではない、顧客一度れますこの秘密は、それはクライアントがJWT自己署名できることを意味することに終わります
アプリケーション
-
一般是在请求头里加入Authorization,并加上 Bearer 标注:
-
fetch('api/user/1', {
-
headers: {
-
'Authorization': 'Bearer ' + token
-
}
-
})
利点:
- JSONの汎用性のため、C#、JavaScriptを、NodeJS、PHPおよび他の多くの言語を使用することができますようにJWTは、クロスランゲージをサポートすることができますので、
- ペイロード部分のため、JWTのビジネスロジックは、独自の非感受性でいくつかの他の必要な情報を格納することができます
- それは非常に簡単に輸送することであるので、輸送の容易さは、JWTの構成は、小さな占有バイト非常に簡単です
- アプリケーションを拡張することは簡単ですので、それは、セッション情報を保存するためにサーバを必要としません。
安全関連
- 部分は、クライアント缶復号化の一部であるので、我々は、JWTのペイロード部分で機密情報を保存しないでください
- 秘密の秘密鍵を保護します。秘密鍵は非常に重要です
- あなたは、httpsプロトコルを使用してくださいすることができた場合
インターネットからの情報、
特定のビュー https://blog.csdn.net/u014799292/article/details/88365086
第二に、戦闘
最初は瓶パッケージに導入しました
<依存>
<groupIdを> io.jsonwebtoken </ groupIdを>
<たartifactId> jjwt </たartifactId>
<バージョン> 0.9.0 </バージョン>
</依存関係>
ツールの新JWT
パブリッククラスJwtTokenUtil {
最終的な静的な文字列= TOKEN_HEADER公共の"認可";
パブリック静的文字列TOKEN_PREFIX決勝= "無記名";
プライベート静的SECRET最終文字列= "jwtsecrettest";
プライベート静的ISS最終文字列= "ヒョウ";
のpublic static finalロングの有効期限= 3600L; //有効期限は1時間
のpublic static final長いEXPIRATION_REMEMBER = 604800L; // 7日の満了後に私の時間を覚えておいてください選択
/ *
*生成トークン方式
* @paramユーザ名
* @param isRemenberMe
* /
パブリック静的文字列createToken(上記のID文字列、文字列ユーザ名、ブールisRemenberMe){
ロングの有効期限= isRemenberMe EXPIRATION_REMEMBER:有効期限;?
//文字列encryId = RCUtils。encry_string(ID)。
リターンJwts.builder()。signWith(SignatureAlgorithm.HS512、SECRET)
.setIssuer(ISS)
.setId(ID)
.setSubject(ユーザー名)
.setIssuedAt(新しいDate())
.setExpiration(新しい日付(のSystem.currentTimeMillis()+有効期限* 1000))
.compact();
}
/ **
*トークンからユーザ名を取得
* @paramトークン
* @return
* @throws BusinessExpection
* /
文字getUsername(文字列トークン)BusinessExpectionスローパブリック静的{
リターンgetTokenBody(トークン).getSubjectを();
}
/ **
*から取得したIDトークン、復号処理を行っている間
* @paramトークン
* @return
* @throws BusinessExpection
* /
パブリック静的な文字列getObjectId(文字列トークン)BusinessExpection {スロー
リターンgetTokenBody(トークン).getId();
}
/ **
*されています有効期限
* @paramトークン
* @throwsは異常ExpiredJwtExceptionを取り込むだけで判断できない期限切れ
* @return
* @throws BusinessExpection
* /
@Deprecated
isExpiration(文字列トークン)ブールのpublic staticをスローBusinessExpection {
。リターンgetTokenBody(トークン).getExpiration()の前に(新しいDate());
}
/ *
*获取トークン信息、同时也做校验处理
*
* /
パブリック静的請求getTokenBody(文字列トークン)がスローBusinessExpection {
試み{
Jwts.parserを(戻り)
.setSigningKey(SECRET)
.parseClaimsJws(トークン)
.getBody() ;
}キャッチ(ExpiredJwtExceptionが満了){
//过期
新しいBusinessExpection(EmBussinsError.TOKEN_EXPIRED)を投げます。
}キャッチ(でSignatureException電子){
//无效
スロー新しいBusinessExpection(EmBussinsError.INVALID_REQUEST)。
}キャッチ(MalformedJwtException malformedJwt){
//无效
スロー新しいBusinessExpection(EmBussinsError.INVALID_REQUEST)。
}
}
}
baseActionで統一GETトークン値
ユーザログがトークン戻る生成された最初のステップ。
@Controller
@RequestMapping( "/管理者")
パブリッククラスAdminControllerはBaseActionを{延び
( "/ログイン")@RequestMapping
@ResponseBody
公衆resultTypeとログイン(HttpServletRequestのリクエスト、HttpServletResponseの応答){
文字列名= request.getParameter( "ユーザ名");
文字列パス= request.getParameter( "パス");
文字列トークン= JwtTokenUtil.createToken( "10"、ユーザ名、偽);
response.setHeader(JwtTokenUtil.TOKEN_HEADER、JwtTokenUtil.TOKEN_PREFIX +トークン)。
ResultType.creat( "sussess")を返します。
}
( "/ adminLoginOut")@RequestMapping
@ResponseBody
公共resultTypeとadminLoginOut(HttpServletRequestのリクエスト)スローBusinessExpection {
文字列のuserId = getUserid(リクエスト)。
ResultType.creat(「成功」)を返します。
}
}
テストが成功し、その後、GETトークンの暗号化の情報ヘッダの種類を返します
ユーザーテストでログインしてました
エラーは、トークンを運ぶことはありません場合は
もちろん、このエラーは、すべてのテストが簡単なので、書き込まれた後、ここで私は、独自のカスタムすることができます。主な機能は、テストすることです
トークン運ぶ、[OK]
操作が成功した場合にはトークンとトークン認証が成功して頂きます。