SpringBoot-JWT生成Token和拦截器
七旅之言 人气:01.什么是JWT
JWT官方的定义是:JSON Web令牌(JWT)是一个开放标准(RFC 7519),用于作为JSON对象在各方之间安全地传输信息。 可以验证和信任该信息,因为它是数字签名的。 jwt可以使用一个秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
其实他本质上就是一个签名
,用于验证用户是否可以请求受限资源
(例如在商城中向服务器请求个人中心页面信息、购物车页面信息)
比如说现在在你家楼下有一家有一家自助餐厅,自助餐厅的门前有一个收银柜台。到了中午你感觉到肚子饿了,去了自助餐厅吃饭,去收银柜台交了钱,收银柜台给你开了一张你交过钱的证明,该证明里写了你什么时候交的钱,交了多少钱等信息,现在你拿着这张证明去餐厅里面吃饭,吃饭时候只要给这张证明就行,因为他认证了你的信息,店员知道你交过钱了也不会让你再交一次,同时防止了你不交钱吃饭的情况。
在这个例子中,我们如果把场景转换到网上商城(前后端分离的情况),收银柜台就是登录,登录完后服务器给你一个证明,证明你登录过了,这个证明有生成的时间、你的信息等等,这时候你想访问购物车,就拿着这个证明发给服务器,服务器验证该证明,验证通过后返回给你想要的数据。
还有一种情况就是如果你没有登录,想直接访问购物车的数据,服务器会发现你没有token(或者你伪造了一个token服务器验证不通过或者token过期),就会让你重新登录,从而实现了拦截访问受限资源的功能。
2.JWT生成token
2.1 添加依赖
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
2.2 生成token
该案例为 在 登录的Controller中,用户的账号密码输入正确,生成token,其中最重要的是token的密码,验证token时候需要使用
JwtBuilder builder = Jwts.builder(); String token = builder.setSubject("userName") .setIssuedAt(new Date()) //设置token生成时间 .setId(u.getUserId() + "")//设置tokenID .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000))//设置过期时间,现在为设置 一天 .signWith(SignatureAlgorithm.HS256, "123456")//设置token密码,解析token需要使用 .compact();
到此token生成完毕,接着返回给前端,前端收到后将其存在cookie当中 这里提供一个设置cookie的工具类代码,设置或者取出cookie可以直接使用 每次前端发送请求时候都在 请求头
中携带token即可
var operator = "="; //取出cookie function getCookieValue(keyStr){ var value = null; var s = window.document.cookie; var arr = s.split("; "); for(var i=0; i<arr.length; i++){ var str = arr[i]; var k = str.split(operator)[0]; var v = str.split(operator)[1]; if(k == keyStr){ value = v; break; } } return value; } //设置cookie function setCookieValue(key,value){ document.cookie = key+operator+value; }
2.3 使用拦截器解析token
配置拦截器
其中ResultVO和ResStatus为封装的返回对象,代码如下:
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class ResultVO { @ApiModelProperty("响应状态码") private Integer code; @ApiModelProperty("响应信息") private String msg; @ApiModelProperty("响应数据") private Object Data; }
public class ResStatus { public static Integer OK = 10000; public static Integer NO = 10001; public static Integer PASS = 20002; }
@Component public class CheckTokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //因为是在请求头中发送token,所以第一次请求的方法为"OPTIONS",具体可以看TCP/IP协议 String method = request.getMethod(); if("OPTIONS".equalsIgnoreCase(method)){ return true; } String token = request.getHeader("token"); System.out.println("token:"+token); if(token == null){ ResultVO resultVO = new ResultVO(ResStatus.NO,"请先登录",null); doResponse(response,resultVO); }else{ try{ //在jwt中,只要token不合法或者验证不通过就会抛出异常 JwtParser parser = Jwts.parser(); parser.setSigningKey("123456"); Jws<Claims> claimsJws = parser.parseClaimsJws(token); return true; }catch (ExpiredJwtException e1) { ResultVO resultVO = new ResultVO(ResStatus.PASS, "登录过期,请重新登录", null); doResponse(response,resultVO); }catch (UnsupportedJwtException e2){ ResultVO resultVO = new ResultVO(ResStatus.NO, "Token不合法,已记录恶意IP", null); doResponse(response,resultVO); }catch (Exception e3){ ResultVO resultVO = new ResultVO(ResStatus.NO, "请先登录", null); doResponse(response,resultVO); } } return false; } @SneakyThrows private void doResponse(HttpServletResponse response, ResultVO resultVO) { response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); String s = new ObjectMapper().writeValueAsString(resultVO); out.print(s); out.flush(); out.close(); } }
设置拦截器拦截的内容
拦截了shopcart的请求,排除了user开头的请求,因为user开头请求负责登录和注册不应被拦截
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Resource private CheckTokenInterceptor checkTokenInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(checkTokenInterceptor) .addPathPatterns("/shopcart/**") .excludePathPatterns("/user/**"); } }
加载全部内容