赞
踩
什么是token验证,我第一次听的时候,感觉非常高大上,但实际上形象的理解就是:
比如你去酒店开一间房,那么在前台的人员会给你一张房卡,规定时间内,你可以用这张房卡访问指定的房间,当时间结束后,那么这张房卡就失效了,需要重新在前台申请
那么token就相当于这张房卡,前台就相当于拦截器,拦截所有用户的请求,并发放房卡,没有房卡或者房卡时间超时的不能再访问房间。
那么实现的过程很好理解了,我们首先需要根据用户登录的账号密码来设定token,这个token包含的基本信息有:用户账号密码,token过期时间等,用户登录以后,返回一个token,然后在访问其他url的时候必须在头文件中携带该token,并且需要检查token是否有效,如果有效,就可以请求成功,无效就返回失败。
那么接下来,我们就看一下这个实现过程
首先,我们需要一个token的工具类,来帮助我们根据用户信息生成token,并且可以检测token:
这里用到了JWT,具体概念可以看这篇文章:什么是JWT?
public class TokenUtil { //设置过期时间 private static final long EXPIRE_DATE=30*60*100000; //token秘钥 private static final String TOKEN_SECRET = "ZCfasfhuaUUHufguGuwu2020BQWE"; public static String token (String username,String password){ String token = ""; try { //过期时间 Date date = new Date(System.currentTimeMillis()+EXPIRE_DATE); //秘钥及加密算法 Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); //设置头部信息 Map<String,Object> header = new HashMap<>(); header.put("typ","JWT"); header.put("alg","HS256"); //携带username,password信息,生成签名 token = JWT.create() .withHeader(header) .withClaim("username",username) .withClaim("password",password).withExpiresAt(date) .sign(algorithm); System.out.println("token: "+token); }catch (Exception e){ e.printStackTrace(); return null; } return token; } public static boolean verify(String token){ /** * @desc 验证token,通过返回true * @params [token]需要校验的串 **/ try { Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); JWTVerifier verifier = JWT.require(algorithm).build(); DecodedJWT jwt = verifier.verify(token); return true; }catch (Exception e){ e.printStackTrace(); return false; } } }
JWT需要导入的依赖:
<!--JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
然后我们需要在用户登录请求中,为其增加token的生成用户的token信息表,由于一段时间会失效,没有永久保存的必要,可以放在缓存中,常见的就是用redis,这里简化了操作,将token信息存入到数据库的一张表中
那么我们在登录请求中就同时为该用户生成一个新的token,save或者update到表中:登录成功后就返回token给前端
好了,现在用户已经有了token,那么我们就需要设定它必须拿此token才能访问内部url,那么就需要拦截器:
public class HeaderTokenInterceptor implements HandlerInterceptor { private final static Logger logger= LoggerFactory.getLogger(HeaderTokenInterceptor.class); @Override public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception { logger.info("filter running...."); ResponseData responseData=null; //获取我们请求头中的token验证字符 String headerToken=request.getHeader("token"); //检测当前页面,我们设置当前页面不是登录注册页面时,对其进行拦截 //检测url中有没有login字符 System.out.println("request url "+request.getRequestURI()); if(!request.getRequestURI().contains("act")){ if(headerToken==null) { //如果token不存在的话,返回错误信息 responseData = ResponseData.customerError(); logger.info("token不存在"); } try { // 对token进行更新与验证 TokenUtil.verify(headerToken); } catch (Exception e) { // 当token验证出现异常返回错误信息,token不匹配 responseData=ResponseData.customerError(); } } if(responseData!=null) {//如果有错误信息 response.getWriter().write(JSON.toJSONString(responseData)); return false; }else { // 将token加入返回页面的header response.setHeader("token", headerToken); return true; } } @Override public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
好了,到这里就完成了token验证的基本操作,
那么接下来就需要前端的配合
前端的任务比较简单,就是将登录返回的token信息存入到sessionStorage
或者是cookies
中
我这里写的demo是放在了cookies中并在请求的时候取出token
实际上这个方法并不是很好,因为如果每次请求都要去获取cookie值会比较的麻烦
在前端写一个拦截器,对每一个请求的url都加上当前用户的token会更好。(我是前端小菜,这部分还有些问题,后面会再做修改)
demo的内容如下,很简单,就是模拟用户登录注册和页面访问
当然这是携带token的
如果不携带token就会拒绝访问,这里我用postman去调用:
前后端代码,我已经上传到git上了,有需要的伙伴可以参考:
https://github.com/IsMrChen/Practice/tree/ssh/ssh/houseDemo
如果文章对你有帮助,不要忘了给我点个赞吼( ̄▽ ̄)~
欢迎关注我的微信公众号:松鼠技术站
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。