SpringBoot 2.xの使用のJWT(JSONウェブトークン)

クロスドメイン認証が遭遇する問題の一つ

マルチ端末の出現に起因して、多くのサイトを通じてweb api restful途中に基づく伝統的な認証に関連することができる分離の終わり頃開発されたモデルを使用して外部サービスの形、でクロスドメインの提出に向け以外に異なるアプローチ、問題の外、もっと重要なのは、いくつかの端末はサポートしていない可能性がありますcookieSession Idcookiecookie

JWT(JSON Web Token)認証および承認スキームは、単に通話が通話を終了することを意味しているapiにはで来るときapi、発行側token、発信者の認証情報を検証するために、。

一般的なプロセスは以下です:

1. 用户向服务器发送用户名和密码。
2. 服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
3. 服务器向用户返回一个 session_id,写入用户的 Cookie。
4. 用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
5. 服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

このモデルの問題は、貧しい人々スケーラビリティです。ユーザがサーバのクラスタ、クロスドメインサービス指向アーキテクチャーまたは無効になっている場合に単一の問題が、ありませんcookie死にます、。

第二に、ソリューション

1.スタンドアロンおよびログインチェック、セッション共有に分散アプリケーション

  • シングルおよびマルチノードtomcatアプリケーションログオンテスト

    ①は、スタンドアローンのtomcatアプリケーションのログインを、sesssionユーザーが正常にログインした後、ブラウザとアプリケーションサーバのセッションの間保存し、サーバーがあることを保証しますsessionクライアントの意志はsessionId、クライアントがしますsessionId保存しcookie、ユーザーの要求はこれを運ぶたびに、sessionId

    ②、マルチノード・tomcatアプリケーション、ログオン開くsessionデータの共有を、各サーバが読み取ることができますsession欠点は、それぞれということであるsessionメモリとリソースを占有され、各サーバ・ノードは、ユーザが何百万レベルのリソースの占有量に達したとき、すなわち、各サーバにデータの複数のコピーを格納する必要があり、ユーザデータの同期を必要とそれは深刻で、ユーザ体験は特に悪いです!

  • 分散アプリケーションsession共有

    ①、実際のアプリケーションは、単一ノードを展開することはできませんので、複数のノードのログインが存在するsession共有解決すべき課題は。tomcatサポートsessionの共有が、ブロードキャストストームがあり、ユーザーに多くの時間、リソースを大量に消費する深刻には、推奨されていません

    ②、Reidsクラスタ、ストレージ着陸token外側にサービス・インターフェースは、Redis(サーバを使用して有効期限を設定することができUUID、ランダム生成する64ビット又は128ビットをtoken、にRedisし、クライアントに戻され、記憶されています)。

    ③、ユーザーが正常にログオン初めて、あなたは自己生成する必要がtoken、その後、tokenブラウザに返され、保存されたcookie中、
    およびRedisサーバー上tokenなどkeyなどのユーザ情報value保存します。その後のユーザ操作ができHttpServletRequest、直接オブジェクトを読み出しcookieているtoken、そしてRedis(各時間は、ユーザがこのアクセスを運ぶの比較が行われ、対応するユーザデータを取得するためtokenにサーバRedisが存在するかどうかを確認するユーザー)。

    ④、短所:展開する必要がありRedis、それぞれが訪問しなければならない、RedisIOコストが特に大きいです。

2.最終的な解決方法:JWTはトークン認証を実現

  • JWT原則

    認証サーバがユーザに戻って、ユーザーとサーバーの通信時間後にJSONオブジェクトを生成した後、我々はJSONオブジェクトを送り返す必要があります。サーバーは、完全にオブジェクト識別されたユーザに依存しています。オブジェクトを生成するとき、データの改ざんからユーザーを防止するために、サーバは、署名が追加されます。そのサーバーはすべてのセッションデータを保存しません、それは、サーバーがステートレス、および拡張を実現することが比較的容易になります。

    简单来说,就是通过一定规范来生成 token,然后可以通过解密算法逆向解密 token,这样就可以获取用户信息
  • 賛否両論

    長所:生産トークンは、そのようなID、ユーザーのニックネーム、アバターやその他の情報など、基本的な情報が含まれている再を避けるために、ライブラリを確認することができ、サーバーのメモリリソースではなく、クライアントに保存されています

    欠点:トークンはbase64エンコードした後、それを復号することができるので、暗号化前のオブジェクトトークンが機密情報を含んではならない(例えば、ユーザのアクセス権、パスワード、等)

  • ヘッド+負荷+署名(ヘッダ+ペイロード+署名):JWT形式は、から成り

    ヘッド:主に署名アルゴリズムを記述します。

    ロード:など、ユーザIDとして、暗号化されたオブジェクトの情報を記述し、また、ISS発行者、有効期限の経験、サブ指向のユーザーとして、仕様内のいくつかのものを追加することができます。

    署名:主要部分は、トークンを改ざんベースを復号化することがトークンを取得するために他の人を防ぐために、最初の2つの暗号化です。

図3.ケースデザイン

第三に、コードは、ケースを示しています

  • そして導入pom.xmlファイル依存エンティティクラス
    <!-- 依赖可以减少实体类 getter/setter等方法书写 -->
    <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <optional>true</optional>
    </dependency>
    <!-- JWT相关 -->
    <dependency>
       <groupId>io.jsonwebtoken</groupId>
       <artifactId>jjwt</artifactId>
       <version>0.7.0</version>
    </dependency>
    
    ====================================================================================
    
    @Getter
    @Setter
    @ToString
    @AllArgsConstructor
    @NoArgsConstructor
    public class User implements Serializable {
    
        private Integer id;
        private String openid;
        private String name;
        private String headImg;
        private String phone;
        private String sign;
        private Integer sex;
        private String city;
        private Date createTime;
    
    }
  • JWT生成ツール
    public class JwtUtil {
    
        // 主题
        public static final String SUBJECT = "RookieLi";
    
        // 秘钥
        public static final String SECRETKEY = "Rookie666";
    
        // 过期时间
        public static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;  //过期时间,毫秒,一周
    
        // 生成 JWT
        public static String geneJsonWebToken(User user) {
    
            if (user == null ||
                    user.getId() == null ||
                    user.getName() == null ||
                    user.getHeadImg() == null) {
    
                return null;
            }
            String token = Jwts.builder()
                    .setSubject(SUBJECT)
                    .claim("id", user.getId())
                    .claim("name", user.getName())
                    .claim("img", user.getHeadImg())
                    .setIssuedAt(new Date())
                    .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                    .signWith(SignatureAlgorithm.HS256, SECRETKEY).compact();
    
            return token;
        }
    
    
        // 校验 JWT
        public static Claims checkJWT(String token) {
    
            try {
                final Claims claims = Jwts.parser().setSigningKey(SECRETKEY).
                        parseClaimsJws(token).getBody();
                return claims;
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
  • JWTのテストツール
    public class JwtUtilTest {
    
        @Test
        public void testGeneJwt(){
    
            User user = new User();
            user.setId(999);
            user.setHeadImg("I'm busy");
            user.setName("Rookie");
            String token = JwtUtil.geneJsonWebToken(user);
            System.out.println(token);
    
        }
    
    
        @Test
        public void testCheck(){
    
            // 下面此 token 字符串是上面的结果生成的,每次不一样,不是写死的
            String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJSb29raWVMaSIsImlkIjo5OTksIm5hbWUiOiJSb29raWUiLCJpbWciOiJJJ20gYnVzeSIsImlhdCI6MTU2NzMxNjk4NywiZXhwIjoxNTY3OTIxNzg3fQ.FJh41VwVh2gh5-_cOG0SOgoO3dR_ZcK9VWNNskWqKl0";
            Claims claims = JwtUtil.checkJWT(token);
            if(claims != null){
                String name = (String)claims.get("name");
                String img = (String)claims.get("img");
                int id =(Integer) claims.get("id");
                System.out.println(name);
                System.out.println(img);
                System.out.println(id);
            }else{
                System.out.println("非法token");
            }
        }
    }

    参考ブログ:

    http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

    https://www.cnblogs.com/jpfss/p/10929458.html

おすすめ

転載: www.cnblogs.com/miantiao312/p/11442187.html