栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot整合JWT实现登录验证

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot整合JWT实现登录验证

1 定义

JWT全称为JSON Web Token,是目前最流行的跨域身份验证解决方案。JWT是为了在网络应用环境间传递声明而制定的一种基于JSON的开放标准。

此信息可以进行验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

JWT特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可被加密。

官方介绍

2 JWT的数据结构

JWT其实就是一个很长的字符串,【将JSON对象进行base64编码拼凑而成】字符之间通过"."分隔符分为三个子串,各字串之间没有换行符。每一个子串表示了一个功能块,总共有三个部分:JWT头(header)、有效载荷(payload)、签名(signature),如下图所示:

2.1 JWT头

JWT头是一个描述JWT元数据的JSON对象,通常如下所示:

{"alg": "HS256","typ": "JWT"}

alg:表示签名使用的算法,默认为HMAC SHA256(写为HS256)

typ:表示令牌的类型,JWT令牌统一写为JWT

最后,使用base64 URL算法将上述JSON对象转换为字符串

2.2 有效载荷

有效载荷,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。

有效载荷部分规定有如下七个默认字段供选择:

iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT

除以上默认字段外,还可以自定义私有字段。

2.3 签名

签名实际上是一个加密的过程,是对上面两部分数据通过指定的算法生成哈希,以确保数据不会被篡改。

首先需要指定一个密码(secret),该密码仅仅保存在服务器中,并且不能向用户公开。然后使用JWT头中指定的签名算法(默认情况下为HMAC SHA256),根据以下公式生成签名哈希:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成整个JWT对象。
请注意,对于已签名的令牌,令牌中包含的所有信息都会向用户或其他方公开,即使他们无法更改它。这意味着您不应将机密信息放在令牌中。

2. 3 JWT签名算法

JWT签名算法中,一般有两个选择:HS256和RS256。

HS256 (带有 SHA-256 的 HMAC )是一种对称加密算法, 双方之间仅共享一个密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。

RS256 (采用SHA-256 的 RSA 签名) 是一种非对称加密算法, 它使用公共/私钥对: JWT的提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。

3JWT的认证机制

在身份验证中,当用户使用其凭据成功登录时,将返回 JSON Web 令牌。在身份验证中,当用户使用其凭据成功登录时,将返回 JSON Web 令牌。
每当用户想要访问受保护的路由或资源时,用户代理都应发送 JWT,通常在授权标头中使用持有者架构。标头的内容应如下所示:

Authorization: Bearer 

4 整合SpringBoot 4.1 相关依赖
  
        
            org.springframework.boot
            spring-boot-starter
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        


        
            io.jsonwebtoken
            jjwt
            0.9.1
        
    
4.2 JWT通用方法
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.io.*;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;


public class JWTUtil {


    
    public String createJWTStrHS256(Map playload,String key){

        //头部JSON数据,固定写法
        MapheaderMap=new HashMap<>();
        //算法HS256
        headerMap.put("alg", SignatureAlgorithm.HS256.getValue());
        headerMap.put("typ", "JWT");

        //使用JJWT提供的API创建JWT
        String s = Jwts.builder()
                //设置头部数据
                .setHeader(headerMap)
                //设置有效荷载数据
                .setClaims(playload)
                //使用HS256签名算法
                .signWith(SignatureAlgorithm.HS256, key)
                .compact();
        return s;
    }

    
    public Object decodeJWTrHS256(String JwtStr,String key){

        //头部JSON数据,固定写法
        MapheaderMap=new HashMap<>();
        //算法HS256
        headerMap.put("alg", SignatureAlgorithm.HS256.getValue());
        headerMap.put("typ","JWT");

        Jwt jwt = Jwts.parser()
                .setSigningKey(key)
                .parse(JwtStr);

        return jwt.getBody();
    }

    
    public void generateRS256Key(String password) throws NoSuchAlgorithmException {

        //钥匙对生成Generator,使用的是RSA算法
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(password.getBytes());
        keyPairGenerator.initialize(1024, secureRandom);
        //获得钥匙对
        KeyPair keyPair = keyPairGenerator.genKeyPair();

        //公钥字节码
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        //私钥字节码
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

        //公私钥匙对信息写入文件
        try {
            FileOutputStream fos=new FileOutputStream("..\pub.key");
            fos.write(publicKeyBytes);
            fos.close();

            FileOutputStream fos_1=new FileOutputStream("..\pri.key");
            fos_1.write(privateKeyBytes);
            fos_1.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    
    public PrivateKey generatePrivateKey( )  {
        try {
            //根据类路径下的pri.key私钥物理文件获得输入流
            InputStream resourceAsStream =
                    this.getClass().getClassLoader().getResourceAsStream("pri.key");
            DataInputStream dis = new DataInputStream(resourceAsStream);
            byte[] keyBytes = new byte[resourceAsStream.available()];
            dis.readFully(keyBytes);
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(spec);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        return null;
    }

    
    public PublicKey generatePublicKey(){
        try {
            //根据类路径下的pri.key私钥物理文件获得输入流
            InputStream resourceAsStream =
                    this.getClass().getClassLoader().getResourceAsStream("pri.key");
            DataInputStream dis = new DataInputStream(resourceAsStream);
            byte[] keyBytes = new byte[resourceAsStream.available()];
            dis.readFully(keyBytes);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePublic(spec);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        return null;
    }

    
    public String createJWTStrRS256(Map playload){

        //头部JSON数据,固定写法
        MapheaderMap=new HashMap<>();
        //算法HS256
        headerMap.put("alg", SignatureAlgorithm.RS256.getValue());
        headerMap.put("typ","JWT");

        PrivateKey key=generatePrivateKey();

        //使用JJWT提供的API创建JWT
        String s = Jwts.builder()
                //设置头部数据
                .setHeader(headerMap)
                //设置有效荷载数据
                .setClaims(playload)
                //使用HS256签名算法
                .signWith(SignatureAlgorithm.RS256, key)
                .compact();
        return s;
    }

    
    public Object decodeJWTrRS256(String JwtStr){
        //头部JSON数据,固定写法
        MapheaderMap=new HashMap<>();
        //算法HS256
        headerMap.put("alg", SignatureAlgorithm.RS256.getValue());
        headerMap.put("typ","JWT");

        PrivateKey key=generatePrivateKey();

        Jwt jwt = Jwts.parser()
                .setSigningKey(key)
                .parse(JwtStr);

        return jwt.getBody();
    }

}

4.3 项目结构

4.4 测试JWT字符串的生成与解析
```@Test
    public void test1(){
        Map playload=new HashMap<>();
        playload.put("userId","100");
        playload.put("tes","test");

        //使用HS256加密算法
        String str = util.createJWTStrHS256(playload, "123456");
        System.out.println(str);

        Object o = util.decodeJWTrHS256(str, "123456");
        System.out.println(o);


        //使用RS256加密算法
        String str1 = util.createJWTStrRS256(playload);
        System.out.println(str1);

        Object o1 = util.decodeJWTrRS256(str1);
        System.out.println(o1);
    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/756664.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号