1.JWT构成
- 头部(header)
- 有效载荷(Payload)
- 签名(signature)
2.header(header是一段json,经过base64编码变成一段字符串,编码前后对比图如图所示:)
- typ:token的类型,这里固定为JWT
- alg:使用的hash算法,例如:HMAC SHA256或者RSA

3.payload
- 存储需要传递的信息,如用户ID、用户名等
- 还包含元数据,如过期时间、发布人等
- 与header不同,payload可以加密
4.signature
- 对header和payload部分进行签名
- 保证token在传输的过程中没有被篡改或者损坏

5.JWT工作原理
客户端通过请求将用户名和密码传给服务端,服务端将用户名和密码进行核对,核对成功后将用户id等其他信息作为jwt的有效载荷(payload)与头部进行base64编码形成jwt(字符串),后端将这段字符串作为登陆成功的返回结果返回给前端。前端将其保存在localstroage或sessionstroage里,退出登录时,删除JWT字符串就可以。
每次请求,前端都会把JWT作为authorization请求头传给后端,后端进行检查。
引入依赖
<!--JTW-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
JWT工具类
public class JWTUtil {
/**
* 生成token
* @return
*/
public static String getToken(User user){
// 创建日期对象
Calendar instance = Calendar.getInstance();
instance.add(Calendar.HOUR, ConfigUtil.outTime);
// 创建token
String token = JWT.create()
.withClaim( "data" , JSONObject.toJSONString(user))
.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(ConfigUtil.sign));
return token;
}
/**
* 验证token合法性,并返回存储的用户信息
* @param token
* @return
*/
public static User verifyToken(String token) throws Exception{
DecodedJWT verify = JWT.require(Algorithm.HMAC256(ConfigUtil.sign)).build().verify(token);
String data = verify.getClaim( "data" ).asString();
User user = JSONObject.parseObject(data, User. class );
return user;
}
}
|
拦截器
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws IOException {
String token = httpServletRequest.getHeader( "token" );
try {
if (token == null ){
returnUnauthorized(httpServletResponse, "没有token" );
return false ;
} else {
JWTUtil.verifyToken(token);
return true ;
}
} catch (TokenExpiredException e){
e.printStackTrace();
returnUnauthorized(httpServletResponse, "token过期" );
} catch (AlgorithmMismatchException e ){
e.printStackTrace();
returnUnauthorized(httpServletResponse, "token算法不一致" );
} catch (Exception e) {
e.printStackTrace();
returnUnauthorized(httpServletResponse, "token无效" );
}
return false ;
}
/**
* 返回权限错误消息
* @param response
* @param msg
* @throws IOException
*/
private static void returnUnauthorized(HttpServletResponse response, String msg) throws IOException {
response.setCharacterEncoding( "utf-8" );
response.setContentType( "application/json;charset=UTF-8" );
JSONObject result = new JSONObject();
result.put( "code" , ConfigUtil.UNAUTHORIZED_CODE);
result.put( "msg" , msg);
response.getWriter().println(result.toString());
}
}
|
两个测试接口
@ApiOperation ( "登录接口" )
@GetMapping ( "/login" )
public AjaxResult login(HttpServletRequest request, HttpServletResponse response){
String token = JWTUtil.getToken( new User(1L, "程力" , new Date(), new Date()));
return AjaxResult.success( "登录成功!" , token);
}
@ApiOperation ( "获取当前用户信息" )
@PostMapping ( "/getLoginUser" )
public AjaxResult getLoginUser(HttpServletRequest request) throws Exception {
String token = request.getHeader( "token" );
User user = JWTUtil.verifyToken(token);
return AjaxResult.success(user);
}
|