JavaとAndroidにおけるJWTの利用
取得元:https://blog.csdn.net/mythmayor/article/details/81221642
I. JWTの紹介
JWTとは、JSON Web Tokenのことです。JSON Web Token (JWT) は、当事者間で安全に情報を転送するためのコンパクトで独立した方法をJSONオブジェクトとして定義したオープンスタンダード(RFC 7519)です。この情報は、デジタル署名によって検証され、信頼されることができます。JWTは、秘密鍵(HMACアルゴリズム使用)またはRSAもしくはECDSAを使用した公開鍵/秘密鍵ペアを使用して署名することができます。
JWTは当事者間の機密保持のために暗号化することができますが、ここでは署名トークンに焦点を当てます。署名トークンはその中に含まれるステートメントの完全性を検証し、暗号化トークンは他のパーティのステートメントを隠します。公開鍵と秘密鍵のペアを使用してトークンに署名する場合、秘密鍵を持つ当事者だけが署名していることも証明されます。
JWTを学び、利用するために、https://jwt.io/ にアクセスしてください。
II. JavaでJWTを使う
まず、JWTをhttps://jwt.io/主页上找到Java项目的入口。ここでは、"maven: com.auth0 / java-jwt / 3.3.0" を選び、項目右下の "View Repo" ボタンをクリックすると、プロジェクトのGithubホームページに飛び、インポートすることができます。ここではインポート手順を直接書いていきますが、このバージョンは執筆時点の最新版です。
メイヴン
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
グラドル
compile 'com.auth0:java-jwt:3.4.0'
1.JWT生成
public String JWTGenerate(String key, String secret, String jwtSecret) {
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("alg", "HS256");
headers.put("typ", "JWT");
String builder = JWT.create().withHeader(hearMap).withClaim("key", key).withClaim("secret", secret).sign(Algorithm. HMAC256(jwtSecret));
return builder;
}
2. JWTのデコード
public void JWTDecode(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
/**
* Header Claims
*/
//Returns the Algorithm value or null if it's not defined in the Header.
String algorithm = jwt.getAlgorithm();
//Returns the Type value or null if it's not defined in the Header.
String type = jwt.getType();
//Returns the Content Type value or null if it's not defined in the Header.
String contentType = jwt.getContentType();
//Returns the Key Id value or null if it's not defined in the Header.
String keyId = jwt.getKeyId();
//Private Claims
Claim claim = jwt.getHeaderClaim("owner");
/**
* Payload Claims
*/
//Returns the Issuer value or null if it's not defined in the Payload.
String issuer = jwt.getIssuer();
//Returns the Subject value or null if it's not defined in the Payload.
String subject = jwt.getSubject();
//Returns the Audience value or null if it's not defined in the Payload.
List<String> audience = jwt.getAudience();
//Returns the Expiration Time value or null if it's not defined in the Payload.
Date expiresAt = jwt.getExpiresAt();
//Returns the Not Before value or null if it's not defined in the Payload.
Date notBefore = jwt.getNotBefore();
//Returns the Issued At value or null if it's not defined in the Payload.
Date issuedAt = jwt.getIssuedAt();
//Returns the JWT ID value or null if it's not defined in the Payload.
String id = jwt.getId();
//Private Claims
Claim claim2 = jwt.getClaim("isAdmin");
} catch (JWTDecodeException exception){
//Invalid token
}
}
三、AndroidにおけるJWTの利用について
当初はAndroidで上記のJavaライブラリを使用していましたが、org.apache.commons.codec.binary.Base64を使用するとAndroidのパッケージと競合することが判明し、ラップしてパッケージ名を変えてみるとうまくいきましたが、これは明らかに最善の解決策とは言えません。そこで、ここでは別のライブラリを使っています。https://jwt.io/主页上找到Java项目的入口 で、"maven: io.jsonwebtoken / jjwt / 0.9.0" を選択しました。この項目の右下にある "View Repo" ボタンをクリックすると、プロジェクトの Github ホームページに飛んで、インポートすることができます。以下、依存ライブラリの仕組みについて簡単に説明します。
Maven
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
Gradleです。
dependencies {
compile 'io.jsonwebtoken:jjwt:0.9.1'
}
1.JWT生成
public String JWTGenerate() {
Map<String, Object> map = new HashMap<>();
map.put("claim1", "claim1value");
map.put("claim2", "claim2value");
String key = Base64.encodeToString("secret".getBytes(), 0);
//Key key = MacProvider.generateKey(SignatureAlgorithm.HS256);
Date exp = new Date(System.currentTimeMillis() + 60 * 1000);//expiration time
String compactJws = Jwts.builder().addClaims(map).setHeaderParam("typ", "JWT")
.signWith(SignatureAlgorithm.HS256, key).setExpiration(exp).compact();
try {
Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);
//OK, we can trust this JWT
} catch (SignatureException e) { //don't trust the JWT!
e.printStackTrace();
} catch (ExpiredJwtException e) {//The key is expiration
e.printStackTrace();
}
return compactJws;
}
2. JWTのデコード
まず、上記の "jjwt" ライブラリを使用して、デコードがどのように動作するかを見てみましょう。
public void JWTParse(String jwt) {
String key = Base64.encodeToString("secret".getBytes(), 0);
//Schlüssel = MacProvider.generateKey(SignatureAlgorithm.HS256);
//在解析的时候一定要传key进去,否则无法通过key的认证
Jwt parse = Jwts.parser().setSigningKey(key).parse(jwt);
Header header = parse.getHeader();
Map<String, Object> map = (Map<String, Object>) parse.getBody();
String param = (String) map.get("param");
}
他にも使えるライブラリがあります。https://github.com/auth0/JWTDecode.Android で勉強して使ってみてください。もちろん、上記のJavaライブラリを使ってデコードすることも可能です。
依存関係を追加する
compile 'com.auth0.android:jwtdecode:1.1.1'
使用すること。
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
JWT jwt = new JWT(token);
/**
* Registrierte Claims
*/
//Returns the Issuer value or null if it's not defined.
String issuer = jwt.getIssuer();
//Returnt den Wert des Betreffs oder null, wenn er nicht definiert ist.
String subject = jwt.getSubject();
//Returnt den Wert Audience oder eine leere Liste, wenn er nicht definiert ist.
List<String> audience = jwt.getAudience();
//Returnt den Wert für die Ablaufzeit oder null, wenn er nicht definiert ist.
Date expiresAt = jwt.getExpiresAt();
//Returnt den Wert Not Before oder null, wenn er nicht definiert ist.
Date notBefore = jwt.getNotBefore();
//Returnt den Wert Issued At oder null, wenn er nicht definiert ist.
Date issuedAt = jwt.getIssuedAt();
//Returnt den Wert der JWT-ID oder null, wenn er nicht definiert ist.
String id = jwt.getId();
//Zeitvalidierung
boolean isExpired = jwt.isExpired(10); // 10 Sekunden Spielraum
/**
* Private Claims
*/
Claim claim = jwt.getClaim("isAdmin");
IV. 遭遇した問題とその治療法
AndroidStudioでコンパイルする場合、以下のような問題が発生します。
解決策は
Moduleのbuild.gradleのandroid{}に以下のコードを追加します。
packagingOptions {
exclude 'META-INF/LICENSE'
}
エラーが報告されているファイルを除外する。
関連
-
GPSプロンプトの問題は、Callがユーザーによって拒否される可能性のある許可を必要とすることです:コードは、明示的にsをチェックする必要があります。
-
com.android.ide.common.process.ProcessException が発生する可能性のある原因。aaptの実行に失敗したエラー(解決済み)
-
警告: 構成 'compile' は廃止され、'implementation' と 'api' に置き換わりました。
-
Android携帯で通常のhttpsのサイトにアクセスすると、最初のリクエストで認証パスのトラストアンカーが見つからないと報告され、その後正常にアクセスできるようになり、問題が解決しました。
-
Intellij Ideaは、シンボルが見つからない、RクラスまたはRパッケージが存在しない、というエラーを報告します。
-
Android Studioのインポートプロジェクトが表示されます。ファイルをクランチするのに失敗しました
-
Android Studio がエラーを報告します。指定された名前に一致するリソースが見つかりませんでした
-
Android Studioのパッケージングプロセスとapk生成時のエラーについて
-
Android TextViewの自動改行問題
-
android.content.ActivityNotFoundException: Intenを処理するアクティビティが見つからない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
com.android.tools.build:gradle:3.0.0 が見つかりませんでした。
-
Dalvik仮想マシンと学習プランの簡単な紹介
-
アプリの実行エラー。デフォルトのアクティビティが見つかりません
-
Android リソースのリンクに失敗する、解決方法
-
エミュレータです。PANIC: AVDのシステムパスが壊れています。ANDROID_SDK_ROOTの値を確認してください。
-
MyEclipseの起動時に以下のようなエラーが発生したため、ログファイルを参照してください。
-
Androidのビューの描画処理を完全に説明し、ビュー(II)を理解するために、ステップバイステップであなたを取る
-
Androidリストウィジェット開発詳細
-
Android TextViewは、あるテキストのカラー・フォント・サイズを設定する
-
AndroidManifestのuses-permissionの設定