Java后端实现token的生成和验证
在Java后端实现token登录功能
什么是token?
token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。
当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。
简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。
为什么要用token?
Token的目的是为了验证用户登录情况以及减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
避免CSRF跨站伪造攻击,支持跨域,适合前后端分离项目。
使用方法
基于JWT的token认证实现
1.引入依赖
1 2 3 4 5
| <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version> </<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version> </dependency>
|
2.创建工具类TokenUtil
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
| public class TokenUtil { private static final long EXPIRE_TIME= 15*60*1000; private static final String TOKEN_SECRET="tokenqkj";
public static String sign(Admin admin){
String token = null; try { Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME); token = JWT.create() .withIssuer("auth0") .withClaim("name", admin.getName()) .withExpiresAt(expiresAt) .sign(Algorithm.HMAC256(TOKEN_SECRET)); } catch (Exception e){ e.printStackTrace(); } return token; }
public static boolean verify(String token){ try { JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build(); DecodedJWT jwt = verifier.verify(token); System.out.println("认证通过:"); System.out.println("issuer: " + jwt.getIssuer()); System.out.println("name: " + jwt.getClaim("name").asString()); System.out.println("过期时间: " + jwt.getExpiresAt()); return true; } catch (Exception e){ return public class TokenUtil { private static final long EXPIRE_TIME= 15*60*1000; private static final String TOKEN_SECRET="tokenqkj";
public static String sign(Admin admin){
String token = null; try { Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME); token = JWT.create() .withIssuer("auth0") .withClaim("name", admin.getName()) .withExpiresAt(expiresAt) .sign(Algorithm.HMAC256(TOKEN_SECRET)); } catch (Exception e){ e.printStackTrace(); } return token; }
public static boolean verify(String token){ try { JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build(); DecodedJWT jwt = verifier.verify(token); System.out.println("认证通过:"); System.out.println("issuer: " + jwt.getIssuer()); System.out.println("name: " + jwt.getClaim("name").asString()); System.out.println("过期时间: " + jwt.getExpiresAt()); return true; } catch (Exception e){ return false; } } }
|
3.创建token拦截器TokenInterceptor **
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
| @Component public class TokenInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception{
if(request.getMethod().equals("OPTIONS")){ response.setStatus(HttpServletResponse.SC_OK); return true; }
response.setCharacterEncoding("utf-8");
String token = request.getHeader("token"); 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","50000"); response.getWriter().append(json.toJSONString()); System.out.println("认证失败,未通过拦截器"); }catch (Exception e){ e.printStackTrace(); response.sendError(500); return false; }
return false;
} @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Headers", "Authorization,Content-Type,X-Requested-With,token"); response.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT,DELETE"); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Max-Age", "3600");
|
4.创建入口拦截器IntercepterConfig
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
| @Configuration 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("/register"); excludePath.add("/api/login"); excludePath.add("/logout"); excludePath.add("/static/**"); excludePath.add("/swagger-ui.html/**"); excludePath.add("/assets/**");
registry.addInterceptor(tokenInterceptor) .addPathPatterns("/**") .excludePathPatterns(excludePath); WebMvcConfigurer.super.addInterceptors(registry);
} @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD") .maxAge(3600 * @Configuration 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("/register"); excludePath.add("/api/login"); excludePath.add("/logout"); excludePath.add("/static/**"); excludePath.add("/swagger-ui.html/**"); excludePath.add("/assets/**");
registry.addInterceptor(tokenInterceptor) .addPathPatterns("/**") .excludePathPatterns(excludePath); WebMvcConfigurer.super.addInterceptors(registry);
} @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD") .maxAge(3600 * 24); } }
|
5.控制类的编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @PostMapping(value = "/api/login") @CrossOrigin public Result login (String name, String password, HttpServletResponse response){ String token=null; Admin admin = service.login(name, password); if (admin != null) { token = TokenUtil.sign(admin); } if(token != null){ return new Result(200,"",token); } else { return new Result(400,"账号密码错误",@PostMapping(value = "/api/login") @CrossOrigin public Result login (String name, String password, HttpServletResponse response){ String token=null; Admin admin = service.login(name, password); if (admin != null) { token = TokenUtil.sign(admin); } if(token != null){ return new Result(200,"",token); } else { return new Result(400,"账号密码错误",""); }
}
|