JWT的原理参考文章
加密和签名–公钥和私钥谁来进行加密,解密的参考文章
为啥公钥加密可以被私钥解密的参考文章。
cookie,session,token的参考文章
主要的参考文章,点击这里
传统session和Jwt和JJWt的使用,参考文章

开篇:

实现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使用的签名】
① 声明类型typ,表示这个令牌(token)的类型(type),JWT令牌统一写为JWT
② 声明加密的算法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的请求数据】
这些有效信息包含三个部分:标准中注册的声明、公共的声明和私有的声明
一、标准中注册的声明:
① iss(issuer): jwt签发者
② sub(subject): jwt所面向的用户,放登录的用户名等
③ aud(audience): jwt接收者
④ exp(expiration time): jwt的过期时间,这个过期时间必须要大于签发时间
⑤ nbf(Not Before): 生效时间,定义在什么时间之前
⑥ iat(issuedAt): jwt的签发时间
⑦ 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;
	}
 
}

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐