1、依赖
1 2 3 4 5 | <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.1</version> </dependency> |
2、JWT工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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、注册拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 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
分类:
Java
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】