ログイン認証: Cookie とセッション テクノロジの代わりに JWT を使用する理由

目次

1. ユーザー認証成功後のログイン情報の保存場所を理解する

-> クッキーとセッションテクノロジー

2. これらのユーザー情報(アカウント、パスワード、権限)の確認方法

3. ステートレスセッション分析

---> Cookie セッションのシングル ログイン

 ----> 中小規模のシングル サインオン設計パターン (比較的シンプル)

 ----> SSO シングル サインオン

4 具体的な実現

1. jwt(トークン)jsonウェブトークン

公式サイト:https://jwt.io

2. テストクラスはトークンの作成とトークンの解析のプロセスを理解します。


1. ユーザー認証成功後のログイン情報の保存場所を理解する

-> クッキーとセッションテクノロジー

Cookie とセッションは非常に一般的な Web 開発テクノロジですが、次の理由により徐々に廃止される予定です。

  1. プライバシーとセキュリティの問題: Cookie に機密情報を保存すると、ハッカーによって盗まれ、損失が生じる可能性があります。さらに、Cookie の有効期限は通常長期にわたるため、ユーザー情報は常にローカルに保存され、悪用される可能性があります。

  2. クロスドメインの問題: ユーザーが複数のドメイン名で同じ Web サイトを使用している場合、異なるドメイン名間での Cookie の受け渡しが妨げられ、ユーザーが Web サイトを使用する際に問題が発生します。

  3. スケーラビリティの問題: Cookie とセッションは HTTP プロトコルに基づいています。Web テクノロジーの発展に伴い、HTTP プロトコルは、WebSocket などの実装が必要な一部のビジネス ニーズを満たすことができなくなりました。

したがって、開発者は、トークンや JWT など、Cookie やセッションに代わる新しいテクノロジーを徐々に採用しています。これらの新しいテクノロジーは、ユーザー情報をより安全に保存し、従来のテクノロジーのいくつかの欠点を克服できます。

2. これらのユーザー情報(アカウント、パスワード、権限)の確認方法

/**
     * 获取登录用户信息
     * 登录成功会存到哪
     * 如何获取登录信息
     * @return
     */
    @GetMapping("/doGetUser")
    public String doGetUser(){
        Authentication authentication =
                SecurityContextHolder.getContext().getAuthentication();
        User principal = (User)authentication.getPrincipal();
        System.out.println("principal.class="+principal.getClass());
        //.getClass 表示获取获取类型
        return principal.getUsername()+","+principal.getAuthorities();
    }

3. ステートレスセッション分析

        3 つのログイン (セッション状態) 設計パターン

---> Cookie セッションのシングル ログイン

単一の直接 Cookie + セッション、小規模ビジネスと古いビジネスが存在しますが、分散システムでは少し味気ないように思えます 

 ----> 中小規模のシングル サインオン設計パターン (比較的シンプル)

 

 ----> SSO シングル サインオン

クライアントはセッション状態を記録し、サーバーはトークンの解析のみを行います。 

登録センター、リモート通話、ログ収集、データベース等の簡略図は省略 

4 具体的な実現

1. jwt(トークン)jsonウェブトークン

公式サイト:https:  //jwt.io

 3 つの部分 JWT は通常、Header (ヘッド)、Payload (ロード)、Signature (署名) の 3 つの部分で構成されます。

xxxxx.yyyyy.zzzzz
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4 fwpMeJf36POk6yJV_adQssw5c

 ---------->

2. テストクラスはトークンの作成とトークンの解析のプロセスを理解します。

package com.cy.jt.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class JwtTests {
    public static final String JWT_SECRET ="AAABBBCCCDDDDEEE";//加密盐
    //测试创建解析token
    @Test
    void testCreateAndParseToken(){
        //创建token(头信息,负载信息,签名信息)
        //1.1 获取登录认证信息(例如用户名,权限)
        Map<String,Object> map=new HashMap<>();
        map.put("username", "pzy");
        map.put("permissions", "sys:res:create,sys:res:retrieve");
//日历对象 Date方法中的方法已经不再推荐使用了 对日期进行加减运算

        Calendar calendar = Calendar.getInstance();//当前时间
        //在当前时间的基础上加30分钟
        calendar.add(Calendar.MINUTE, 30);
        Date expirationTime = calendar.getTime();//获取30分钟后的时间
        System.out.println("expirationTime:==>"+expirationTime);

//jwts方法创建token
        String token = Jwts.builder()
                .setSubject("jwt")//主题
                .setClaims(map)// 负载信息(登录信息,没有密码)
                //.setExpiration(new Date(System.currentTimeMillis() + 30 * 1000))//过期时间
                .setExpiration(expirationTime)//过期时间
                .setIssuedAt(new Date())//签发时间
                .signWith(SignatureAlgorithm.HS256,JWT_SECRET)//设置签名加密算法和盐
                .compact();//制作token
        System.out.println("token:===>"+token);
        //解析token
//eyJhbGciOiJub25lIn0.eyJwZXJtaXNzaW9ucyI6InN5czpyZXM6Y3JlYXRlLHN5czpyZXM6cmV0cmlldmUiLCJleHAiOjE2MzQ4NzM1MjAsImlhdCI6MTYzNDg3MzQ5MCwidXNlcm5hbWUiOiJqYWNrIn0.

        Claims claims = Jwts.parser()
                .setSigningKey(JWT_SECRET)
                .parseClaimsJws(token) //最爱出错的问题
                .getBody();
        System.out.println("claims: ===> "+claims);


    }
}

セキュリティ面では、jwtと連携して認証やログイン認証の動作を実現し、oauth2では動作手順を簡略化し、基本パラメータの引き渡しと@beanのインジェクションを行っています。

パスワードもバックグラウンドの平文レコードから md5 プラス ソルト暗号化に変更され、bcrypt 暗号化に変更されます。

通常、インターセプターで使用されます

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");

        // 验证token的过程
        if (verifyToken(token)) {
            return true;
        } else {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception {
    }

    private boolean verifyToken(String token) {
        // 进行token的验证
        // 如果验证成功返回true,否则返回false
    }
}
 

おすすめ

転載: blog.csdn.net/pingzhuyan/article/details/120884364