1. ホーム
  2. Android

JavaとAndroidにおけるJWTの利用

2022-02-23 20:56:22
<パス
取得元: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'
}


エラーが報告されているファイルを除外する。