利用JWT生成Token的原理及公钥和私钥加密和解密的原则
开篇:实现Token的方式有很多,本篇介绍的是利用Json Web Token(JWT)生成的Token.JWT生成的Token有什么好处呢?安全性比较高,加上密匙加密而且支持多种算法。携带的信息是自定义的,而且可以做到验证token是否过期。验证信息可以由前端保存,后端不需要为保存token消耗内存。小知识:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一...
文章目录
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;
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)