利用JWT生成Token的原理及公钥和私钥加密和解密的原则

开篇:

        实现Token的方式有很多,本篇介绍的是利用Json Web Token(JWT)生成的Token.JWT生成的Token有什么好处呢?

  • 安全性比较高,加上密匙加密而且支持多种算法。
  • 携带的信息是自定义的,而且可以做到验证token是否过期。
  • 验证信息可以由前端保存,后端不需要为保存token消耗内存。

        小知识:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。

什么是JWT?

        JSON Web Token 简称JWT。
        一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
        JWT生成的token是这样的

eyJpc3MiOiJKb2huI.eyJpc3MiOiJ.Kb2huIFd1IEp

        生成的token,是3段,用.连接。下面有解释。其中:前两段头部和载荷都是通过Base64进行编码的,最后一段是将前两段连接在一起,然后在通过相应的加密算法(这里HS256)进行加密过后的字符串。

头部

        用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。
        头部(header)是一个JSON对象,一般使用Base64URL编码,承载两部分信息,存放一些声明信息,如:用什么加密,用什么编码【作用:指定JWT使用的签名】

  1. 声明类型type,表示这个令牌(token)的类型(type),JWT令牌统一写为JWT
  2. 声明加密的算法alg,通常直接使用HMAC SHA256,也可以使用RSA,支持很多算法(HS256、HS384、HS512、RS256、RS384、RS512、ES256、ES384、ES512、PS256、PS384)

加密算法详解,点击这里
        HS开头的是HMAC-SHAX。是利用HAMC对SHA摘要算法进行加盐(秘钥)哈希。
其他三个均是利用非对称算法加密进行签名,再对结果进行摘要得出的结果。


例如:

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

载荷

        其实就是自定义的数据,一般存储用户Id,过期时间等信息。也就是JWT的核心所在,因为这些数据就是使后端知道此token是哪个用户已经登录的凭证。而且这些数据是存在token里面的,由前端携带,所以后端几乎不需要保存任何数据。
        注意:在载荷里面不应该加入任何敏感的数据,因为它直接可以通过Base64就能进行解码了。
        载荷也叫消息体(payload)是一个JSON对象,一般使用Base64URL编码,存放主要的有用信息,如:登陆的用户名,登录时间,登录的过期时间,还可以放一些自定义信息【作用:指定JWT的请求数据】
        这些有效信息包含三个部分:标准中注册的声明、公共的声明和私有的声明
        一、标准中注册的声明:

  1.  iss(issuer): jwt签发者
  2.  sub(subject): jwt所面向的用户,放登录的用户名等
  3.  aud(audience): jwt接收者
  4.  exp(expiration time): jwt的过期时间,这个过期时间必须要大于签发时间
  5.  nbf(Not Before): 生效时间,定义在什么时间之前
  6.  iat(issuedAt): jwt的签发时间
  7.  jti(JWT ID): jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

        二、公共的声明:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密
        三、私有的声明:私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。 

        例如:

{
  "uid": "xxxxidid",  //用户id
  "exp": "12121212"  //过期时间
}

签名

        签名其实就是:

  1. 头部和载荷各自base64加密后用.连接起来,然后就形成了xxx.xx的前两段token。
  2. 最后一段token的形成是,前两段加入一个密匙用HS256算法或者其他算法加密形成。

         所以token3段的形成就是在签名处形成的。

        最主要的目的:服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次签名,如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token,返回一个HTTP 401 Unauthorized响应。

 1.使用io.jsonwebtoken包的方式

 pom.xml导入的jar包

<dependencies>
    <!-- Base64加密包,如果加入Tomcat运行环境就可以不用导入 -->
    <!-- <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.10</version>
    </dependency> -->
    <!-- jjwt包 -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.6.0</version>
    </dependency>
    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
</dependencies>

User实体

package com.jjwt.entity;
 
/**
 * @ClassName: User
 * @Description: 用户实体
 */
public class User { 
    private int id;
    private String username;
    private String password;
 
    public User() {
        super();
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
    }
 
}

JjwtUtil类

package com.jwt.utils; 

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; 
import org.apache.tomcat.util.codec.binary.Base64; 
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; 
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
 
// 使用io.jsonwebtoken包
public class JjwtUtil {
 
    // jti:jwt的唯一身份标识
    public static final String JWT_ID = UUID.randomUUID().toString();
 
    // 加密密文,私钥
    public static final String JWT_SECRET = "jiamimiwen";
 
    // 过期时间,单位毫秒
    public static final int EXPIRE_TIME = 60 * 60 * 1000; // 一个小时
//    public static final long EXPIRE_TIME = 7 * 24 * 3600 * 1000; // 一个星期
 
    // 由字符串生成加密key
    public static SecretKey generalKey() {
        // 本地的密码解码
        byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);
        // 根据给定的字节数组使用AES加密算法构造一个密钥
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
 
    // 创建jwt
    public static String createJWT(String issuer, String audience, String subject) throws Exception {
        // 设置头部信息
//        Map<String, Object> header = new HashMap<String, Object>();
//        header.put("typ", "JWT");
//        header.put("alg", "HS256");
        // 或
        // 指定header那部分签名的时候使用的签名算法,jjwt已经将这部分内容封装好了,只有{"alg":"HS256"}
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        // 创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证的方式)
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", "admin");
        claims.put("password", "010203");
        // jti用户id,例如:20da39f8-b74e-4a9b-9a0f-a39f1f73fe64
        String jwtId = JWT_ID;
        // 生成JWT的时间
        long nowTime = System.currentTimeMillis();
        Date issuedAt = new Date(nowTime);
        // 生成签名的时候使用的秘钥secret,切记这个秘钥不能外露,是你服务端的私钥,在任何场景都不应该流露出去,一旦客户端得知这个secret,那就意味着客户端是可以自我签发jwt的
        SecretKey key = generalKey();
        // 为payload添加各种标准声明和私有声明
        JwtBuilder builder = Jwts.builder() // 表示new一个JwtBuilder,设置jwt的body
//                .setHeader(header) // 设置头部信息
                .setClaims(claims) // 如果有私有声明,一定要先设置自己创建的这个私有声明,这是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明
                .setId(jwtId) // jti(JWT ID):jwt的唯一身份标识,根据业务需要,可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击
                .setIssuedAt(issuedAt) // iat(issuedAt):jwt的签发时间
                .setIssuer(issuer) // iss(issuer):jwt签发者
                .setSubject(subject) // sub(subject):jwt所面向的用户,放登录的用户名,一个json格式的字符串,可存放userid,roldid之类,作为用户的唯一标志
                .signWith(signatureAlgorithm, key); // 设置签名,使用的是签名算法和签名使用的秘钥
        // 设置过期时间
        long expTime = EXPIRE_TIME;
        if (expTime >= 0) {
            long exp = nowTime + expTime;
            builder.setExpiration(new Date(exp));
        }
        // 设置jwt接收者
        if (audience == null || "".equals(audience)) {
            builder.setAudience("Tom");
        } else {
            builder.setAudience(audience);
        }
        return builder.compact();
    }
 
    // 解密jwt
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey key = generalKey(); // 签名秘钥,和生成的签名的秘钥一模一样
        Claims claims = Jwts.parser() // 得到DefaultJwtParser
                .setSigningKey(key) // 设置签名的秘钥
                .parseClaimsJws(jwt).getBody(); // 设置需要解析的jwt
        return claims;
    }
 
}

TestJjwt测试类

package com.jwt.test; 

import java.text.SimpleDateFormat; 
import com.alibaba.fastjson.JSON;
import com.jwt.entity.User;
import com.jwt.utils.JjwtUtil; 
import io.jsonwebtoken.Claims;
 
// 使用io.jsonwebtoken包
public class TestJjwt {
 
    public static void main(String[] args) {
        User user = new User();
        user.setId(10);
        user.setUsername("张三");
        user.setPassword("123123");
        // jwt所面向的用户,放登录的用户名等
        String subject = JSON.toJSONString(user);
        try {
            // "Jack"是jwt签发者,"李四"是jwt接收者
            String jwt = JjwtUtil.createJWT("Jack", "李四", subject);
            System.out.println("JWT:" + jwt);
            System.out.println("JWT长度:" + jwt.length());
            System.out.println("\njwt三个组成部分中间payload部分的解密:");
            Claims c = JjwtUtil.parseJWT(jwt);
            System.out.println("jti用户id:" + c.getId());
            System.out.println("iat登录时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(c.getIssuedAt()));
            System.out.println("iss签发者:" + c.getIssuer());
            System.out.println("sub用户信息列表:" + c.getSubject());
            System.out.println("exp过期时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(c.getExpiration()));
            System.out.println("aud接收者:" + c.getAudience());
            System.out.println("登录的用户名:" + c.get("username"));
            // 或
            System.out.println("登录的用户名:" + c.get("username", String.class));
            System.out.println("登录的密码:" + c.get("password", String.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
}

打印的结果

JWT:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJpZFwiOjEwLFwicGFzc3dvcmRcIjpcIjEyMzEyM1wiLFwidXNlcm5hbWVcIjpcIuW8oOS4iVwifSIsImF1ZCI6IuadjuWbmyIsInBhc3N3b3JkIjoiMDEwMjAzIiwiaXNzIjoiSmFjayIsImV4cCI6MTU2NzUwOTYyMiwiaWF0IjoxNTY3NTA2MDIyLCJqdGkiOiJjYjkyMjlkMi1mMDRiLTQ2NmUtOGY4Ny1iMGM4OWU3YWQ5NDEiLCJ1c2VybmFtZSI6ImFkbWluIn0.UG7aVfmQO28bRTrCyD1u2C8pKYXONZ2FZ_R7aFYhJN0
JWT长度:352
 
jwt三个组成部分中间payload部分的解密:
jti用户id:cb9229d2-f04b-466e-8f87-b0c89e7ad941
iat登录时间:2019-09-03 18:20:22
iss签发者:Jack
sub用户信息列表:{"id":10,"password":"123123","username":"张三"}
exp过期时间:2019-09-03 19:20:22
aud接收者:李四
登录的用户名:admin
登录的用户名:admin
登录的密码:010203

2.使用com.auth0包的方式

2.1 pom.xml文件

<properties>
    <!-- Spring版本号 -->
    <spring.version>5.1.5.RELEASE</spring.version>
</properties>
 
<dependencies>
    <!-- junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!-- spring core 核心 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--spring bean bean的管理 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--spring context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--spring context support -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- spring web -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- spring mvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- spring tx -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- spring jdbc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- spring El表达式 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- spring test -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <!-- jwt的包 -->
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.5.0</version>
    </dependency>
    <!-- jjwt包 -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.6.0</version>
    </dependency>
    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
</dependencies>

User实体使用上面的

2.2 JWTInterceptor拦截器

package com.jwt.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; 
import com.jwt.utils.JWTUtil; 
import io.jsonwebtoken.Claims;
 
public class JWTInterceptor implements HandlerInterceptor {
    
    @Autowired
    private JWTUtil jWTUtil;
 
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object obj, Exception e)
            throws Exception {
 
    }
 
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView mav)
            throws Exception {
 
    }
 
    // 拦截每个请求
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) {
        System.out.println("开始进入拦截器检验jwt头部是否含有Authorization方法!");
        // 通过url得到token请求头是否包含Authorization
        String jwt = request.getHeader("Authorization");
        System.out.println(jwt);
        try {
            // 检测请求头是否为空
            if (jwt == null) {
                System.out.println("用户未登录,验证失败");
            } else {
                Claims c = jWTUtil.parseJWT(jwt);
                System.out.println("用户[ " + c.get("username") + " ]已是登录状态");
                System.out.println("结束进入拦截器检验jwt头部是否含有Authorization方法!");
                return true;
            }
            System.out.println("token解析错误,验证失败");
            response.getWriter().write("未登录,请重新登录后操作");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
 
}

2.3 spring-context.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
 
    <!-- 开启注解扫描,对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
    <context:component-scan base-package="com.jwt" />
 
    <!-- 开启注解驱动,启动基于Spring MVC的注解功能,将控制器与方法映射加入到容器中 -->
    <mvc:annotation-driven />
 
    <!-- 接口跨域配置 -->
    <mvc:cors>
        <!-- allowed-methods="*" 表示所有请求都有效 -->
        <mvc:mapping path="/**" allowed-origins="*"
            allowed-methods="*"
            allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
            allow-credentials="true" />
    </mvc:cors>
 
    <!-- 拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径,任何请求都要被拦截 -->
            <mvc:mapping path="/**" />
            <!-- 排除对指定路径的拦截,不拦截user/dologin -->
            <mvc:exclude-mapping path="/user/dologin" />
            <!-- 定义<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
            <bean class="com.jwt.interceptor.JWTInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors> 
</beans>

2.4 web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1">
 
    <servlet>
        <servlet-name>jwt</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jwt</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
 
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping> 
</web-app>

2.5 JWTUtil类

package com.jwt.utils;
 
import java.util.Date; 
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; 
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.stereotype.Component; 
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier; 
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
 
/**
 * 
 * @ClassName: JWTUtil
 * @Description: 实现对用户名和密码的加密处理,校验token是否正确,获取用户名等操作
 * Algorithm algorithm = Algorithm.HMAC256(password) 是对密码进行加密后再与用户名混淆在一起
 * 在签名时可以通过 .withExpiresAt(date) 指定token的过期时间
 * @param:
 */
@Component
public class JWTUtil {
 
    // 过期时间,单位毫秒
    private static final long EXPIRE_TIME = 60 * 1000; // 1分钟
//    private static final long EXPIRE_TIME = 15 * 60 * 1000; // 15分钟
 
    // 加密密文,私钥
    private static final String TOKEN_SECRET = "jiamimiwen";
    
    // 由字符串生成加密key
    public SecretKey generalKey() {
        System.out.println("进入由字符串生成加密key方法!");
        // 本地的密码解码
        byte[] encodedKey = Base64.decodeBase64(TOKEN_SECRET);
        // 根据给定的字节数组使用AES加密算法构造一个密钥
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
 
    // 生成签名
    public String sign(int id, String username, String password) {
        System.out.println("生成签名方法开始执行!");
        try {
            // 设置过期时间,单位毫秒
            Date expTime = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            // 私钥和加密算法
            Algorithm algorithm = Algorithm.HMAC256(password); //使用用户输入的密码
//            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            // 设置头部信息,也可以不用设置头部信息jwt会自动生成
//            Map<String, Object> header = new HashMap<String, Object>();
//            header.put("typ", "JWT");
//            header.put("alg", "HS256");
            // 或
            // header.put("Type", "JWT");
            //    header.put("alg", "HS256");
            // 生成JWT的时间
            Date issuedAt = new Date(System.currentTimeMillis());
            // 返回token字符串
            System.out.println("生成签名方法结束执行!");
            return JWT.create() // 表示new一个Jwt,设置jwt的body
//                    .withHeader(header) // 设置头部信息
                    .withClaim("id", id) // 数据库中用户的id
                    .withClaim("username", username) // 前端输入的用户名
                    .withIssuedAt(issuedAt) // jwt的签发时间
                    .withExpiresAt(expTime) // jwt过期时间
                    .sign(algorithm);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 
     * @Title: verify
     * @Description: 检验token是否正确
     * @param: @param token 密钥
     * @param: @param username 登录名
     * @param: @param password 密码
     * @param: @return
     * @return: boolean
     * @throws
     */
    public boolean verify(String token, String username, String password) {
        System.out.println("进入检验token是否正确方法!");
        try {
            Algorithm algorithm = Algorithm.HMAC256(password); //使用用户输入的密码
//            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();
//            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
 
    // 获取登录名
    public String getUsername(String token) {
        System.out.println("进入获取登录名方法!");
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }
    
    // 解密jwt
    public Claims parseJWT(String jwt) throws Exception {
        System.out.println("进入解密jwt方法!");
        SecretKey key = generalKey(); // 签名秘钥,和生成的签名的秘钥一模一样
        Claims claims = Jwts.parser() // 得到DefaultJwtParser
                .setSigningKey(key) // 设置签名的秘钥
                .parseClaimsJws(jwt).getBody(); // 设置需要解析的jwt
        return claims;
    }
 
}

2.6 UsersController层

package com.jwt.controller;
 
import java.util.HashMap;
import java.util.Map; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; 
import com.jwt.entity.User;
import com.jwt.utils.JWTUtil;
 
@RestController
@RequestMapping("user")
public class UserController {
 
    @Autowired
    private JWTUtil jWTUtil;
 
    @PostMapping("dologin")
    public Map<String, Object> dologin(@RequestParam String username, @RequestParam String password) {
//    public Map<String, Object> dologin(@RequestBody User user) {
        System.out.println("dologin方法开始执行!");
        int id = 10;
        User user = new User();
        user.setId(id);
        user.setUsername(username);
        user.setPassword(password);
//        String username = user.getUsername();
//        String password = user.getPassword();
        Map<String, Object> map = new HashMap<String, Object>();
        if ("admin".equals(username) && "123456".equals(password)) {
            String token = jWTUtil.sign(id, username, password);
            if (token != null) {
                map.put("code", "200");
                map.put("message", "认证成功!");
                map.put("token", token);
                map.put("data", user);
                System.out.println("dologin方法结束执行----认证成功!");
                return map;
            }
        } else {
            map.put("code", "000");
            map.put("message", "认证失败!");
            System.out.println("dologin方法结束执行----认证失败!");
        }
        return map;
    }
 
    @GetMapping("list")
    public Map<String, Object> list() {
        System.out.println("list方法开始执行!");
        Map<String, Object> map = new HashMap<String, Object>();
        User user = new User();
        user.setId(1001);
        user.setUsername("张三");
        user.setPassword("123123");
        map.put("users", user);
        System.out.println("list方法结束执行!");
        return map;
    }
 
}

原文链接:https://blog.csdn.net/weixin_42030357/article/details/95629924

猜你喜欢

转载自blog.csdn.net/Aplumage/article/details/120745344