:Java实现基于JWT的Token生成和验证(终于成功了)
原创:Java实现基于JWT的Token生成和验证(终于成功了)
为了实现这个token,我历经断断续续的差不多一个星期才解决(话说,最近我工作是真的闲,这才有时间学习),快哉,快哉。
当我一个星期前,想要在自己的项目中集成token时,思考了一下,感觉需要集成网关gateway作为前提,所以还费尽心思的在自己项目中先集成了spring cloud gateway(尴尬)。
虽然过程曲折,也不需要gateway作为前提,但是过程中还是学习到了很多很多。
好了,接下来是正题,一如既往地是保姆式的从头到尾讲解:
ps:如果要了解token的作用,请百度,这里不赘述了。
第一步是加入依赖:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.5.0</version>
</dependency>
第二步是写一个基于jwt的token帮助类,用于token生成和验证
/**
* @Author YuanChangLiang
* @Date 2020/11/10 20:47
*/
public class TokenUtil {
/**
* token过期时间
*/
private static final long EXPIRE_TIME = 30 * 60 * 1000;
/**
* token秘钥
*/
private static final String TOKEN_SECRET = "YuanChangLiang";
/**
* 生成签名,30分钟过期
* @param username 用户名
* @param loginTime 登录时间
* @return 生成的token
*/
public static String sign(String username, String loginTime) {
try {
// 设置过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
// 私钥和加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
// 设置头部信息
Map<String, Object> header = new HashMap<>(2);
header.put("Type", "Jwt");
header.put("alg", "HS256");
// 返回token字符串
return JWT.create()
.withHeader(header)
.withClaim("loginName", username)
.withClaim("loginTime", loginTime)
.withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 检验token是否正确
* @param token 需要校验的token
* @return 校验是否成功
*/
public static boolean verify(String token){
try {
//设置签名的加密算法:HMAC256
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e){
return false;
}
}
}
第三步是登录的方法实现类
/**
* 登录
* @param loginVo 登录类
* @return 返回类
*/
@Override
public R login(LoginVo loginVo) {
User user = new User();
user.setUserName(loginVo.getUserName());
user.setPassword(loginVo.getPassword());
List<User> users = userService.queryByUser(user);
if(users.isEmpty()){
return R.fail();
}else{
if(loginVo.getUserName() != null && loginVo.getLoginTime() != null) {
String token = TokenUtil.sign(loginVo.getUserName(), loginVo.getLoginTime());
loginVo.setToken(token);
//断言token不为空,并以用户名作为key,存入redis
assert token != null;
redisTemplate.opsForValue().set(loginVo.getUserName(),token);
return R.ok(loginVo);
}else{
return R.fail();
}
}
}
第四步是添加拦截器类
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("Authorization");
if (token != null) {
boolean result = TokenUtil.verify(token);
if (result) {
System.out.println("通过拦截器");
return true;
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
try {
JSONObject json = new JSONObject();
json.put("success", "false");
json.put("msg", "认证失败,未通过拦截器");
json.put("code", "500");
response.getWriter().append(json.toJSONString());
System.out.println("认证失败,未通过拦截器");
} catch (Exception e) {
e.printStackTrace();
response.sendError(500);
return false;
}
return false;
}
}
第五步是添加配置拦截器的类
/**
* @author YuanChangLiang
* @Date now
*/
@Component
public class IntercepterConfig implements WebMvcConfigurer {
private TokenInterceptor tokenInterceptor;
//构造方法
public IntercepterConfig(TokenInterceptor tokenInterceptor){
this.tokenInterceptor = tokenInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry){
List<String> excludePath = new ArrayList<>();
//登录
excludePath.add("/login/acount");
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
//除了登陆接口其他所有接口都需要token验证
WebMvcConfigurer.super.addInterceptors(registry);
}
}
第六步在postman测试
1.先调用登录方法,获取token(ps:登录方法的返回值中要带token)
1.如果在请求头中不加token
2.如果在请求头中携带token
只有登录方法时不会被拦截的,其他任何请求都会要求携带token才能请求成功,可以很好的防止非法用户的恶意请求。
算了,考虑到某些没耐心,或者相对新手的道友,我给大家看看我的项目的部分结构
loginVo实体类
/**
* @Author YuanChangLiang
* @Date 2020/11/4 12:04
*/
@Data
public class LoginVo {
/**
* 操作码(1:注册 0:登录)
*/
private Integer option;
/**
* 用户名
*/
private String userName;
/**
* 用户密码
*/
private String password;
/**
* token
*/
private String token;
/**
* 登录时间
*/
private String loginTime;
}
别嫌弃我写这么详细,问就是为了适合所有人,为了让所有寻找实现token方法的道友都可以成功。
我实在是受够了这几天为了查找如何实现token,一个个的博客都是给一个token生成和验证类就完事了,掐头去尾的,其他啥也不说,阅读感觉极度极度极度差。。。。。。。。。。
----我是“道祖且长”,一个在互联网苟且偷生的Java程序员
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)