1、依赖
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.1</version> </dependency>
2、JWT工具类
package com.jay.SpringBootStudy8.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
/**
* Jwt工具类
*/
public class JwtUtil {
//自定密钥,最好搞长一点
public static final String tokenKey = "jay2021";
/*
生成票证
*/
public static String getSign(HashMap<String,Object> headMap,HashMap<String,String> claimMap,int days){
LocalDateTime localDateTime = LocalDateTime.now().plus(days, ChronoUnit.DAYS);
Date date = LocalDateTimeUtil.localDateTimeToDate(localDateTime);
JWTCreator.Builder builder = JWT.create().withHeader(headMap);
claimMap.forEach((key, value) -> {
builder.withClaim(key, value);
});
builder.withExpiresAt(date);
String token = builder.sign(Algorithm.HMAC256(tokenKey));
return token;
}
/*
获取token信息,token不对会异常
*/
public static DecodedJWT verify(String token){
DecodedJWT verify = JWT.require(Algorithm.HMAC256(tokenKey)).build().verify(token);
return verify;
}
}
3、日期工具类LocalDateTimeUtil
package com.jay.SpringBootStudy8.utils;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
public class LocalDateTimeUtil {
/**
* LocalDateTime转毫秒时间戳
* @param localDateTime LocalDateTime
* @return 时间戳
*/
public static Long localDateTimeToTimestamp(LocalDateTime localDateTime) {
try {
ZoneId zoneId = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zoneId).toInstant();
return instant.toEpochMilli();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 时间戳转LocalDateTime
* @param timestamp 时间戳
* @return LocalDateTime
*/
public static LocalDateTime timestampToLocalDateTime(long timestamp) {
try {
Instant instant = Instant.ofEpochMilli(timestamp);
ZoneId zone = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zone);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Date转LocalDateTime
* @param date Date
* @return LocalDateTime
*/
public static LocalDateTime dateToLocalDateTime(Date date) {
try {
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
return instant.atZone(zoneId).toLocalDateTime();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* LocalDateTime转Date
* @param localDateTime LocalDateTime
* @return Date
*/
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
try {
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime.atZone(zoneId);
return Date.from(zdt.toInstant());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
4、JWT拦截器,在请求头的Authorization中携带token
package com.jay.SpringBootStudy8.config;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jay.SpringBootStudy8.utils.JwtUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.HashMap;
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
HashMap<String,Object> res = new HashMap<>();
res.put("state",false);
String authStr = request.getHeader("Authorization");
try {
DecodedJWT verify = JwtUtil.verify(authStr);
res.put("state",true);
return true;
}catch (SignatureVerificationException e) {
e.printStackTrace();//无效签名
res.put("msg","无效签名");
}catch (TokenExpiredException e){
e.printStackTrace();//token过期
res.put("msg","token过期");
}catch (AlgorithmMismatchException e){
e.printStackTrace();//算法不一致
res.put("msg","算法不一致");
}catch (Exception e){
e.printStackTrace();//token无效
res.put("msg","token无效");
}
String json = new ObjectMapper().writeValueAsString(res);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
}
5、注册拦截器
package com.jay.SpringBootStudy8.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CustomerMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor()).addPathPatterns("/scanner/getCompanies");
}
}
6、登录生成token、获取token信息、验证拦截器,登录使用的是Shiro
package com.jay.SpringBootStudy8.controller;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.jay.SpringBootStudy8.pojo.SysUser;
import com.jay.SpringBootStudy8.utils.JwtUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class ScannerController {
/*
登录,生成token
*/
@PostMapping("/scanner/login")
public HashMap<String,Object> login(String name, String pwd) {
HashMap<String,Object> res = new HashMap<>();
res.put("state",false);
//MD5加密
ByteSource credentialsSalt = ByteSource.Util.bytes(name);
Object obj = new SimpleHash("MD5", pwd, credentialsSalt, 1);
String pwd2 = obj.toString();
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//封装登录数据
UsernamePasswordToken token = new UsernamePasswordToken(name, pwd2);
try {
//执行登录方法
subject.login(token);
Session session = subject.getSession();
SysUser user = (SysUser) session.getAttribute("user");
// 登录成功,生成票证
HashMap<String,Object> headMap = new HashMap<>();
HashMap<String,String> claimMap = new HashMap<>();
claimMap.put("userId",Integer.toString(user.getId()));
claimMap.put("userName",user.getUserName());
String signStr = JwtUtil.getSign(headMap,claimMap,7);
res.put("state",true);
res.put("msg","登录成功");
res.put("token",signStr);
} catch (UnknownAccountException e) {
res.put("msg","用户名不存在");
} catch (IncorrectCredentialsException e) {
res.put("msg","密码错误");
}
return res;
}
/*
获取token信息 authStr 如果是这种格式 Bearer token 需要把Bearer和空格替掉。
*/
@PostMapping("/scanner/checkToken")
public Map<String, String> checkToken(@RequestHeader("Authorization")String authStr){
DecodedJWT verify = JwtUtil.verify(authStr);
Map<String, Claim> claims = verify.getClaims();
Map<String,String> res = new HashMap<>();
claims.forEach((key,value)->{
res.put(key,value.asString());
});
return res;
}
/*
拦截请求
*/
@PostMapping("/scanner/getCompanies")
public Map<String,String> getCompanies(){
Map<String,String> res = new HashMap<>();
res.put("ali","阿里巴巴");
res.put("baidu","百度");
return res;
}
}
视频:https://www.bilibili.com/video/BV1i54y1m7cP?p=1
浙公网安备 33010602011771号