jwt进行token校验 -详细版
jwt的一些介绍简单使用描述,代码中使用演示添加JWT的依赖以及项目依赖<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></depend
·
jwt的一些介绍
简单使用描述,
代码中使用演示
添加JWT的依赖 以及项目依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--jwt的依赖-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.3</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.5.RELEASE</version>
</plugin>
</plugins>
</build>
application.yml配置文件
server:
port: 8080
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8
username: root
password: root
mybatis:
type-aliases-package: com.test.jwtToken.entity #包映射
configuration:
map-underscore-to-camel-case: true #驼峰
controller代码
/**
* 测试使用session生成token信息给浏览器端,下次浏览器访问就会携带此信息在cookie中.这是以前的校验用户的方式
*/
@RestController
public class SessionTokenApplication {
@GetMapping("/test")
public String sessionToken(HttpServletRequest request) {
request.getSession().setAttribute("userId", UUID.randomUUID());
return "ok";
}
/**
* 用户登录的接口,校验数据库之后,调用token工具类生成token返回客户端
*
* @param user 用户信息
* @return 返回的信息
*/
@Autowired
private UserService userService;
@PostMapping("/login")
public Map<String, String> login(@RequestBody User user) {
User userDb = userService.login(user);
if (userDb == null) {
throw new RuntimeException("用户不存在");
}
//用户校验成功
HashMap<String, String> map = new HashMap<>();
map.put("userName", userDb.getName());
String token = jwtUtil.getToken(map);
HashMap<String, String> resultMap = new HashMap<>();
resultMap.put("state", "认证成功");
resultMap.put("token", token);
return resultMap;
}
/**
* 请求时候带着token,对token进行解析,正确返回成功信息,不成功,抛出对应的异常
* @param token token令牌信息
* @return 验证的信息
*/
@PostMapping("/verify")
public Map<String,Object> verify(String token) {
HashMap<String, Object> map = new HashMap<>();
try {
//调用token解析的工具类进行解析
DecodedJWT verifyToken = jwtUtil.verifyToken(token);
//解析成功,返回成功的信息
map.put("state", true);
map.put("msg", "认证成功!");
return map;
} catch (SignatureVerificationException e) {
e.printStackTrace();
map.put("msp", "签名不一致异常");
} catch (TokenExpiredException e) {
e.printStackTrace();
map.put("msg", "令牌过期异常");
} catch (AlgorithmMismatchException e) {
e.printStackTrace();
map.put("msg", "算法不匹配异常");
} catch (InvalidClaimException e) {
e.printStackTrace();
map.put("msg", "失效的payload异常");
} catch (Exception e) {
e.printStackTrace();
map.put("msg", "token无效");
}
map.put("state", false);
return map;
}
/**
* 拦截器拦截校验token
* @param user
* @return
*/
@GetMapping("/interceptorVerify")
public String jwtInterceptorVerify(@RequestBody User user) {
//拦截器会拦截所有请求,此处进行正常的业务逻辑即可
//查询用户名是否存在
User userDb = userService.login(user);
if (userDb == null) {
return "用户不存在";
}
return "用户存在";
}
}
service接口
public interface UserService {
User login(User user);
}
serviceImpl接口实现类
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User login(User user) {
User userDb = userMapper.login(user);
return userDb;
}
}
mapper接口
public interface UserMapper {
User login(User user);
}
mapper的xml映射
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--PUBLIC:头文件约束,告知此文件是什么文件-->
<!--namespace:映射的命名空间为,接口的相对地址-->
<mapper namespace="com.test.jwtToken.mapper.UserMapper">
<select id="login" resultType="User">
select * from `user` where `name`= #{name} and `password`=#{password}
</select>
</mapper>
实体类
@Data
public class User {
private Integer id;
private String name;
private String password;
}
JWT生成token 和 解析token 的工具类
public class jwtUtil {
//秘钥加密解密都需要用到,所以定义成静态常量
public static final String SIGNATURE = "miyao";
/**
* 生成token
* @param map payload中需要放置的相关非敏感信息
* @return 返回的生成的token信息
*/
public static String getToken(Map<String,String> map) {
//设置一个时间,作为令牌的过期时间 ,设置过期时间为7天
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 7);
//创建jwt builder
JWTCreator.Builder builder = JWT.create();
//遍历map集合,将信息放到payload中
map.forEach((k,v)->{
builder.withClaim(k,v); //payload信息
});
//header信息可以省略,因为默认已经有算法和类型了,也可以在headerMap中设置算法
HashMap<String, Object> headerMap = new HashMap<>();
String token = builder.withHeader(headerMap) //header信息
.withExpiresAt(calendar.getTime()) //token过期时间
.sign(Algorithm.HMAC256(SIGNATURE));//签名
return token;
}
/**
* 验证token DecodedJWT 为解密之后的对象 可以获取payload中添加的数据
*/
public static DecodedJWT verifyToken(String token) {
//进行token的校验,注意使用同样的算法和同样的秘钥
return JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
}
/**
* 获取token中payload中的添加的参数 演示
* @return
*/
public static DecodedJWT getTokenPayloadParam(String token) {
DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
//Map<String, Claim> claims = verify.getClaims(); //获取payload中所有的参数
//verify.getClaim("userName").asString(); //通过key获取value,转成对应的类型
return verify;
}
}
每个方法都进行token校验太过麻烦,
设置拦截器,在方法前进行token解析校验
/**
* 添加拦截器,拦截请求,校验token
*/
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HashMap<String, Object> map = new HashMap<>();
String token = request.getHeader("token"); //从request中获取到请求头中的token,进行解析校验
try {
jwtUtil.verifyToken(token);//调用token解析的工具类进行解析
return true; //请求放行
} catch (SignatureVerificationException e) {
e.printStackTrace();
map.put("msg", "签名不一致异常");
} catch (TokenExpiredException e) {
e.printStackTrace();
map.put("msg", "令牌过期异常");
} catch (AlgorithmMismatchException e) {
e.printStackTrace();
map.put("msg", "算法不匹配异常");
} catch (InvalidClaimException e) {
e.printStackTrace();
map.put("msg", "失效的payload异常");
} catch (Exception e) {
e.printStackTrace();
map.put("msg", "token无效");
}
//map异常的数据要返回给客户端需要转换成json格式 @ResponseBody 内置了jackson
String resultJson = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(resultJson);
return false; //异常不放行
}
}
设置拦截器的拦截规则,放行规则
@Configuration
public class interceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
.addPathPatterns("/interceptorVerify/**") //拦截所有的路径
.excludePathPatterns("/login/**"); //放行login目录下的,因为生成token的方法拦截就无法生成token了
}
}
测试类中进行jwt生成token 与解析token的单独测试
public class JwtTokenTest {
/**
* 令牌的获取
* 测试生成jwt的token令牌三部分组成
* header(加密算法,类型) . payload(负载,可以不重要可以用得到的用户信息) . signature(签名,前两部跟base64加密和自己的秘钥)
*/
@Test
public void jwtToken() {
HashMap<String, Object> map = new HashMap<>();//header中需要传递的map,无内容时使用jwt默认值
//设置一个时间,作为令牌的过期时间 ,设置过期时间为60秒
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 60);
String token = JWT.create().withHeader(map)//header中已经有默认的算法和类型
.withClaim("userId", 123456) //payload负载
.withClaim("userName", "zhangsan") //payload可以传递多个
.withExpiresAt(calendar.getTime()) //令牌不是无限期的,设置令牌的过期时间
.sign(Algorithm.HMAC256("miyao"));//签名设计加密算法,还有设置自己的秘钥
System.out.println(token);
}
/**
* 解析token,注意有效期内
*/
@Test
public void verifyTest() {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("miyao")).build();
DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6InpoYW5nc2FuIiwiZXhwIjoxNjIyMTIwNzgzLCJ1c2VySWQiOjEyMzQ1Nn0.wCobBUz5oRVmeaTBT5Omo_Ab3iTid8JrXRfqmxC-wqs");
//解析完成之后可以获取payload负载中自包含放置的信息
System.out.println(verify.getClaims());
System.out.println(verify.getClaim("userId").asInt());
System.out.println(verify.getClaim("userName").asString());
//获取过期时间
System.out.println(verify.getExpiresAt());
}
}
更多推荐
已为社区贡献3条内容
所有评论(0)