流程:
1.用户访问login接口,验证用户身份信息,并生成token绑定用户信息,token返回前端
2.前端把token存入request header中访问后端接口即可成功,否则提示无权访问
代码部分:
1.JwtUtil类 (生成token,校验token等)
/* *
* @Author qy
* <p> JWT工具类 </p>
* @Param
* @Return
*/
public class JwtUtil {
// Token过期时间30分钟
public static final long EXPIRE_TIME = 30 * 60 * 1000;
/* *
* @Author qy
* <p> 校验token是否正确 </p>
* @Param token
* @Param username
* @Param secret
* @Return boolean
*/
public static boolean verify(String token, String username, String secret) {
try {
// 设置加密算法
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.build();
// 效验TOKEN
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
/* *
* @Author qy
* <p>生成签名,30min后过期 </p>
* @Param [username, secret]
* @Return java.lang.String
*/
public static String sign(String username, String secret) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息
return JWT.create()
.withClaim("username", username)
.withExpiresAt(date)
.sign(algorithm);
}
/* *
* @Author qy
* <p> 获得用户名 </p>
* @Param [request]
* @Return java.lang.String
*/
public static String getUserNameByToken(HttpServletRequest request) {
String token = request.getHeader("token");
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username")
.asString();
}
}
2.JwtInterceptor (拦截请求类,校验错误返回错误信息)
/**
* @Author qinyi
* <p>token验证拦截器 </p>
*/
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
SysUserService sysUserService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从 http 请求头中取出 token
String token = request.getHeader("token");
// 如果不是映射到方法直接通过
if(!(handler instanceof HandlerMethod)){
return true;
}
if (token != null){
String username = JwtUtil.getUserNameByToken(request);
// 这边拿到的 用户名 应该去数据库查询获得密码,简略,步骤在service直接获取密码
boolean result = JwtUtil.verify(token,username,sysUserService.getPassword(username));
if(result){
System.out.println("通过拦截器");
return true;
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null ;
try {
JSONObject res = new JSONObject();
res.put("success", "false");
res.put("msg", "您无权访问");
out = response.getWriter();
out.append(res.toString());
}catch (Exception e){
e.printStackTrace();
response.sendError(500);
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
3. InterceptorConfig (拦截器配置类注入spring管理,配置只放通login,拦截其他所有请求,并支持跨域)
/* *
* @Author qy
* <p>拦截器配置 </p>
* @Param
* @Return
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/* *
* @Author qy
* <p> 设置拦截路径 </p>
* @Param [registry]
* @Return void
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/sysuser/login");
}
/* *
* @Author qy
* <p> 将拦截器注入context </p>
* @Param []
* @Return com.zszxz.jwt.interceptor.JwtInterceptor
*/
@Bean
public JwtInterceptor authenticationInterceptor() {
return new JwtInterceptor();
}
/* *
* @Author qy
* <p>跨域支持 </p>
* @Param [registry]
* @Return void
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD")
.maxAge(3600 * 24);
}
}
4.controller层示例
/**
* @author qinyi
* @since 2021-07-22 10:40:42
*/
@CrossOrigin
@RestController
@RequestMapping("sysuser")
public class LoginController {
/**
* 服务对象
*/
@Resource
private SysUserService sysUserService;
@PostMapping("login")
public ResponseData queryPaper(HttpServletRequest request,@RequestBody SysUser sysUser){
ResponseData res = ResponseData.ok();
String username = sysUser.getUserName();
String password = sysUser.getPassword();
//账号密码验证
String token = JwtUtil.sign(username,password);
if(null != token){
res.putDataValue("token",token);
}else {
res = ResponseData.unauthorized();
}
return res;
}
}
5.pom.xml引入
<!-- 引入jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
6.postman访问成功结果
token过期或错误-失败结果