JWTを使用したユーザー登録tokenチェック

7644 ワード

一、JWTとは
JWTはJSON Web Tokenと呼ばれ、header(ヘッダ)、payload(キャリア)、signature(署名)の3つの部分から構成されている.技術の発展に従って、分布式web応用の普及、sessionを通じてユーザーのログイン状態を管理するコストはますます高くなって、そのためゆっくりとtokenの方式に発展してログインの身分検査をして、それからtokenを通じてredisの中のキャッシュのユーザー情報を取りに行って、その後jwtの出現に従って、検査の方式は更に簡単で便利化して、redisキャッシュを通過する必要はありません保存したユーザー情報をtokenに直接取り出したり、tokenの可用性チェックをしたりするのではなく、単一のログインが簡単です.
  • header JWTの第1部分はheaderで、headerは主に2つの部分を含んで、algは暗号化のタイプを指して、オプションの値はHS 256、RSAなどで、typ=JWTは固定の値で、tokenのタイプを表します.
  • Payload JWT第2部はpayload、payloadはtokenの詳細で、一般的にiss(発行者)、exp(期限切れ)、sub(ユーザー情報)、aud(受信者)、その他の情報が含まれています.詳細は公式サイトを参照してください.カスタムフィールドも含まれています.
  • 
    {
        "iat": 1493090001,
        "name": "  "
    }
    
    iss:Issuer,   
    sub:Subject,  
    aud:Audience,  
    exp:Expiration time,    
    nbf:Not before
    iat:Issued at,    
    jti:JWT ID
    
  • signature JWTの第2の部分はsignatureであり、この部分の内容はこのように計算された:
  • 1、EncodeString = Base64(header).Base64(payload)
    2、  token = HS256(EncodeString,"  ")
    

    署名は、メッセージが転送中に変更されたかどうかを検証するために使用され、秘密鍵署名を使用するtokenの場合、JWTの送信者が送信者と呼ばれているかどうかを検証することもできます.
    二、JSON Web Tokensはどのように働いているのか
    ユーザーが保護されたルーティングまたはリソースにアクセスしたい場合、ユーザーエージェント(通常はブラウザ)はJWTを持参する必要があります.典型的には、通常はAuthorization headerに配置され、Bearer schemaを使用します.
    ヘッダーはこう見えるはずです.
    Authorization: Bearer
    サーバ上の保護されたルーティングは、Authorization headerのJWTが有効かどうかを確認し、有効であれば、ユーザーは保護されたリソースにアクセスできます.JWTに十分な必要なデータが含まれている場合は、必ずしもそうではないかもしれませんが、いくつかの操作に対するデータベース・クエリーの必要性を低減できます.
    tokenがAuthorization headerで送信された場合、クッキーが使用されないため、ソース間リソース共有(CORS)は問題になりません.
    -検証プロセス
  • 署名検証
  • 受信者がJWTを受信した場合、まず署名認証であるこのJWTの完全性を検証する.その検証方法は実は簡単で、headerをbase 64 urlで復号すれば、JWTがどのアルゴリズムで署名したかを知ることができ、このアルゴリズムを使って、再び同じ論理でheaderとpayloadに署名し、この署名がJWT自身が含む3番目の部分の列と完全に同じかどうかを比較し、異なる限り、このJWTは改ざんされたシリアルであり,当然検証に失敗したと考えられる.受信者が署名を生成するときは、JWT送信者と同じ鍵を使用する必要があります.これは、鍵の安全な転送または共有を行うことを意味します.
  • キャリア検証
  • iss(Issuser):発行時にこのclaimの値が「a.com」である場合、検証時にこのclaimの値が「a.com」でない場合は検証に失敗します
    sub(Subject):発行時にこのclaimの値が「liuyunzhuge」である場合、検証時にこのclaimの値が「liuyunzhuge」でない場合は検証に失敗します
    aud(Audience):署名時にこのclaimの値が「['b.com','c.com'」である場合、検証時にこのclaimの値は少なくともb.com,c.comのいずれかを含んで検証する必要があります.
    exp(Expiration time):検証時にこのclaimが指定した時間を超えた場合、検証に失敗します.nbf(Not Before):検証時にこのclaimが指定した時間より小さい場合は、検証に失敗します.
    iat(Issued at):maxAgeなどの検証に使用できます.検証時間がこのclaimで指定した時間と異なる時間がmaxAgeで指定した値より大きい場合は、検証に失敗します.
    jti(JWT ID):発行時にこのclaimの値が「1」である場合、検証時にこのclaimの値が「1」でない場合は検証に失敗します
    注意:JWTを検証する場合、署名認証は実装ライブラリごとに自動的に行われますが、payloadの認証は使用者によって決まります.JWTには標準的なclaimが含まれていない可能性があるため、これらのclaimは自動的に検証されません.
    ログイン認証では、JWTを発行する際に、subとexpの2つのclaimだけを完全に使用し、subでユーザーのidを格納し、expで今回のログイン後の期限切れ時間を格納し、検証時にexpというclaimだけを検証してセッションの有効期間管理を実現することができます.
    三、実戦DEMO
  • 検証プロセス
  • 1.ユーザはユーザ名とパスワードを携帯してアクセスを要求する.サーバはユーザ認証情報3を検証する.アプリケーションはクライアント4にtokenを提供する.クライアントはtokenを格納し、その後のリクエストごとに5.サーバはtokenを検証し、データを返します.
  • 注意
  • リクエストごとにtoken
  • が必要です.
  • Tokenは要求ヘッダの
  • に置くべきである.
  • すべてのドメインからの要求を受け入れるようにサーバを設定する必要があります.Access-Clontrol-Allow-Origin:*
  • 1、関連pomの導入
            
                io.jsonwebtoken
                jjwt-api
                0.10.5
            
            
                io.jsonwebtoken
                jjwt-impl
                0.10.5
                runtime
            
            
                io.jsonwebtoken
                jjwt-jackson
                0.10.5
                runtime
            
            
                com.auth0
                java-jwt
                3.2.0
            
    

    2.JWT生成解析ツールクラスの作成
    
    public class JWTUtils {
        public static String createJWT(String id,String subject,long ttlMillis,SecretKey key){
            //      
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
            long nowMillis = System.currentTimeMillis();
            Date now = new Date(nowMillis);
    
            JwtBuilder builder = Jwts.builder()
                    .setId(id)
                    .setSubject(subject)
                    .setIssuer("user")
                    .setIssuedAt(now)
                    .signWith(key,signatureAlgorithm);
            if(ttlMillis >= 0){
                long expMillis = nowMillis + ttlMillis;
                Date expDate = new Date(expMillis);
                //      
                builder.setExpiration(expDate);
            }
            return builder.compact();
    
        }
    
    
        public static Claims parseJWT(String jwt,SecretKey keySpec){
            return Jwts.parser()
                    .setSigningKey(keySpec)
                    .parseClaimsJws(jwt)
                    .getBody();
        }
    
        public static ResultCode validateJWT(String jwt){
            ResultCode checkResult = new ResultCode();
            Claims claims = null;
            try {
                claims = parseJWT(jwt);
                checkResult.setSuccess(true);
                checkResult.setClaims(claims);
            } catch (ExpiredJwtException e) {
                checkResult.setErrCode("    ");
                checkResult.setSuccess(false);
            }
            return checkResult;
        }
        public static void main(String[] args) {
            //    
            SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    
            String jwt = JWTUtils.createJWT("1","test",10000,key);
            System.out.println(jwt);
            System.out.println(JWTUtils.parseJWT(jwt,key));
        }
    }
    
    

    3、コントローラ層コード
  • ログインロジック
  •     @RequestMapping("/login")
        public String login(    ){
            //           
            ......
            ......
            //        token  
            String jwt = JWTUtils.createJWT(    );
            return jwt;
        }
    
  • ユーザ認証が必要なすべてのインタフェースロジック
  • 
        //        ,                        
    
        public String toIndex(HttpServletRequest request){
            //  token
            String authorization = request.getHeader("authorization");
            if(authorization == null){
                //    
                return "    ";
            }else{
                //    
                try{
                    Claims claims = JWTUtils.parseJWT(authorization);
                    return "   gong";
                }catch (Exception e){
                    e.printStackTrace();
                    return "    ";
                }
            }
    
        }
    

    3、クライアントコード
  • ユーザ情報を入力し、
  • への登録を申請する.
    
        $.ajax({
            url:'http://localhost:8080/demo/login',
            type:'GET',
            data:userLoginData,
            success:function(res) {
                localStorage.setItem("token",res)
            },
            error:function (res) {
                alert(res)
    
            }
    
        })
    
  • 認証インタフェースが要求する場合
  • .
    var token = localStorage.getItem("token");
    
    $.ajax({
            url:'http://localhost:8080/demo/toIndex',
            type:'GET',
            header:{
                'Authorization':token
            },
            beforeSend : function(request) {
                request.setRequestHeader("Authorization",token );
            },
            success:function(res) {
              
            },
        })
    

    四、参考接続
    https://github.com/jwtk/jjwt#install-jdk-maven http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html https://www.jianshu.com/p/f25d62305c70 https://www.cnblogs.com/cjsblog/p/9277677.html https://www.jianshu.com/p/fe67b4bb6f2c