标签:catch 计算 actor ret 数据 发件人 用户登录 lse 生成
在上一节中 session 共享功能使用 redis 进行存储,用户量激增时会导致 redis 崩溃,而 JWT 不依赖服务器,能够避免这个问题。
http协议本身是一种无状态的协议,如果用户向服务器提供了用户名和密码来进行用户认证,下次请求时,用户还要再一次进行用户认证才行。因为根据http协议,服务器并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储─份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样应用就能识别请求来自哪个用户。
Json web token (JWT) ,是一种基于 JSON的开放标准(RFC 7519),定义了一种简洁的、自包含的方法用于通信双方之间以 JSON 对象的形式安全的传递信息。 因为数字签名的存在,这些信息是可信的,JWT 可以使用 HMAC 算法或者 RSA 的公钥私钥进行签名。
就是令牌token,是一个String字符串,由3部分组成,中间用点隔开,令牌组成:
- 标头(Header)
- 有效载荷(Payload)
- 签名(Signature)
token格式:head.payload.singurater 如:xxxxx.yyyy.zzzz
{
"alg" : "HS256",
"type" : "JWT"
}
{
"sub" : "123",
"name" : "John Do",
"admin" : true
}
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret);
<!--引入JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.0</version>
</dependency>
public class JWTUtils {
//自定义密钥
private static final String SECRET_KEY = "@Tes*RI#s&";
/**
* 生成token
*
* @param map
* @return token
*/
public static String createToken(Map<String, String> map) {
JWTCreator.Builder builder = JWT.create();
//保存用户信息
map.forEach((k,v)-> {
builder.withClaim(k,v);
});
Calendar instance = Calendar.getInstance();
instance.add(Calendar.MINUTE,200);
//设置过期时间
builder.withExpiresAt(instance.getTime());
//设置签名
return builder.sign(Algorithm.HMAC256(SECRET_KEY));
}
/**
* 验证token
* @param token
* @return 验证信息
*/
public static Map verify(String token){
Map<String, Object> map = new HashMap<>();
try {
JWT.require(Algorithm.HMAC256(SECRET_KEY)).build().verify(token);
map.put("status", true);
return map;
}catch (TokenExpiredException e){
e.printStackTrace();
map.put("msg","token过期");
}catch (SignatureVerificationException e) {
e.printStackTrace();
map.put("msg", "无效签名");
}catch (AlgorithmMismatchException e) {
e.printStackTrace();
map.put("msg","算法不一致");
}catch (Exception e) {
e.printStackTrace();
map.put("msg","token无效");
}
map.put("status", false);
return map;
}
}
常见异常信息如下:
SignatureVerificationException //签名不一致异常
TokenExpiredException //令牌过期异常
AlgorithmMismatchException //算法不匹配异常
InvalidClaimException //失效的payload异常(传给客户端后,token被改动,验证不一致)
public class AccessFilter implements Filter {
Logger logger = LoggerFactory.getLogger(AccessFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//登录接口不用验证token
if (request.getRequestURI().contains("/login")){
filterChain.doFilter(request, servletResponse);
return;
}
//验证token
String token = request.getHeader("token");
Map<String, Object> map = JWTUtils.verify(token);
//验证成功
if ((Boolean)map.get("status")) {
DecodedJWT decodedJWT = JWTUtils.getToken(token);
logger.info("=========" + decodedJWT.getClaim("userName").asString());
//验证失败
} else {
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json; charset=UTF-8");
response.getWriter().println(json);
return;
}
filterChain.doFilter(request, servletResponse);
}
@Override
public void destroy() {
}
}
@GetMapping(value = "/login")
@ResponseBody
public Result login(HttpSession session) {
Map<String, String> map = new HashMap<>();
map.put("userId", "1");
map.put("userName", "123456");
//生成token
String token = JWTUtils.createToken(map);
return ResultUtil.success(token);
}
返回 token 给客户端,客户端每次请求携带token,过滤器对 token 有效性进行校验,验证成功返回数据,验证失败返回登录页面。
参考资料:JWT详细教程及使用
标签:catch 计算 actor ret 数据 发件人 用户登录 lse 生成
原文地址:https://www.cnblogs.com/CF1314/p/14705744.html