:Java实现基于JWT的Token生成和验证(终于成功了)

:Java实现基于JWT的Token生成和验证(终于成功了)

原创:Java实现基于JWT的Token生成和验证(终于成功了)

为了实现这个token,我历经断断续续的差不多一个星期才解决(话说,最近我工作是真的闲,这才有时间学习),快哉,快哉。 当我一个星期前,想要在自己的项目中集成token时,思考了一下,感觉需要集成网关gateway作为前提,所以还费尽心思的在自己项目中先集成了spring cloud gateway(尴尬)。 虽然过程曲折,也不需要gateway作为前提,但是过程中还是学习到了很多很多。

好了,接下来是正题,一如既往地是保姆式的从头到尾讲解:

ps:如果要了解token的作用,请百度,这里不赘述了。

第一步是加入依赖:

com.auth0

java-jwt

3.5.0

第二步是写一个基于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 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 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 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程序员

更多创意

铎字笔画写法
77365bet体育在线投注

铎字笔画写法

📅 06-27 🔥 7097
450克等于多少斤
365沙巴体育注册

450克等于多少斤

📅 07-16 🔥 5830
《刺激战场》沙漠地图皮卡多适合落点吗 沙漠地图皮卡多分析