jwtdemo 实现
一、添加依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.2</version>
</dependency>
二、jwt配置(写在yml文件里即可)
jwt:
secret: 6913cbb4bbfc53feb70b06ed00cd47ea
## 过期时间 单位分钟,整数
exp: 1440
三、utils

1.JwtProperties 读取yml配置文件
@Component @ConfigurationProperties(prefix = "jwt") @Data public class JwtProperties { /** * 密钥 */ private String secret; /** * 过期时间,单位为分钟 */ private Integer exp; }
2.TokenUser用户信息封装类,可根据自己的业务类型去定义
@Data public class TokenUser { /** * 用户ID存到token中 */ String id; /** * 用户openid */ String openId; /** * 团长id */ String leaderId; }
3.PassToken 注解,用于不校验token的方法
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface PassToken { boolean required() default true; }
4.TokenService 及其实现
public interface TokenService { String getToken(TokenUser user); }
@Service public class TokenServiceImpl implements TokenService { private final JwtProperties jwtProperties; public TokenServiceImpl(JwtProperties jwtProperties) { this.jwtProperties = jwtProperties; } @Override public String getToken(TokenUser user) { JWTCreator.Builder builder = JWT.create(); //withAudience()存入需要保存在token的信息,这里我把用户id和openId存入token中 builder.withAudience(JSONObject.toJSONString(user)); //添加Token过期时间 long expMillis = System.currentTimeMillis() + Long.valueOf(jwtProperties.getExp()*60*1000); Date exp = new Date(expMillis); builder.withExpiresAt(exp); return builder.sign(Algorithm.HMAC256(jwtProperties.getSecret())); } }
四、controller,获取token,UserService需替换成自己的业务接口
@RestController public class TokenController extends BaseController { private final TokenService tokenService; private final UserService userService; public TokenController(TokenService tokenService, UserService userService) { this.tokenService = tokenService; this.userService = userService; } @ApiOperation("微信用户获取token") @PassToken @PostMapping("/wx/token") public ResponseEntity getToken(@RequestBody GetTokenQuery tokenQuery) { //查询微信用户表Id WechatUser userWx = null; if(StringUtils.isNotBlank(tokenQuery.getOpenId())){ userWx = userService.findUserByOpenid(tokenQuery.getOpenId()); }else if(StringUtils.isNotBlank(tokenQuery.getMobile())){ //手机号不为空,解密手机号,去获取微信用户表信息 byte[] mobileByte = Base64.getDecoder().decode(tokenQuery.getMobile()); userWx = userService.findUserByMobile(new String(mobileByte)); } if(userWx != null){ TokenUser tokenUser = new TokenUser(); tokenUser.setId(userWx.getUserId()); tokenUser.setOpenId(userWx.getSmallOpenId()); return new ResponseEntity<>(new ResponseResult<>(HttpStatus.OK.value(), tokenService.getToken(tokenUser), "获取token成功"), HttpStatus.OK); }else{ return new ResponseEntity<>(new ResponseResult<>(ServiceException.Problems.EXCEPTION.getCode(), null, "获取token失败"), HttpStatus.OK); } } }
五.拦截器
1.添加拦截器,WechatUserMapper需替换成自己的业务接口
public class AuthenticationInterceptor implements HandlerInterceptor { private Logger logger = LoggerFactory.getLogger(AuthenticationInterceptor.class); @Autowired private WechatUserMapper wechatUserMapper; @Autowired private JwtProperties jwtProperties; @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception { //拒绝频繁请求 String ip = httpServletRequest.getRemoteAddr(); String url = httpServletRequest.getRequestURL().toString(); if(url.contains("swagger")) return true; //验证token String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token // 如果不是映射到方法直接通过 if(!(object instanceof HandlerMethod)){ return true; } HandlerMethod handlerMethod=(HandlerMethod)object; Method method=handlerMethod.getMethod(); //检查是否有passtoken注释,有则跳过认证 if (method.isAnnotationPresent(PassToken.class)) { PassToken passToken = method.getAnnotation(PassToken.class); if (passToken.required()) { return true; } } // 执行认证 if (token == null) { throw new ServiceException( ServiceException.Problems.SMALL_LOGIN_AUTHORIZE_FAIL_EXCEPTION.getCode(), "无token,请重新授权"); } // 获取 token 中的 user id TokenUser tokenUser; try { tokenUser = JSONObject.parseObject( JWT.decode(token).getAudience().get(0), TokenUser.class); } catch (JWTDecodeException e) { logger.error("解析userId失败" + e.getMessage()); throw new ServiceException( ServiceException.Problems.SMALL_LOGIN_AUTHORIZE_FAIL_EXCEPTION.getCode(), "认证失败,请重新授权"); } WechatUser user = wechatUserMapper.selectByPrimaryKey(tokenUser.getId()); if (user == null) { throw new ServiceException( ServiceException.Problems.SMALL_LOGIN_AUTHORIZE_FAIL_EXCEPTION.getCode(), "用户不存在,请重新授权"); } // 验证 token JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(jwtProperties.getSecret())).build(); try { jwtVerifier.verify(token); } catch (JWTVerificationException e) { logger.error("校验token失败" + e.getMessage()); throw new ServiceException( ServiceException.Problems.SMALL_LOGIN_AUTHORIZE_FAIL_EXCEPTION.getCode(), "授权超过有效时间,请重新授权"); } return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
2.配置拦截器
@Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authenticationInterceptor()) .addPathPatterns("/**"); } @Bean public AuthenticationInterceptor authenticationInterceptor() { return new AuthenticationInterceptor(); } }
完毕 !
浙公网安备 33010602011771号