irpas技术客

原创:Java实现基于JWT的Token生成和验证(终于成功了)_三七有脾气_java jwt token生成

网络 6145

原创: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程序员


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #JAVA #JWT #token生成 #Cloud #gateway尴尬