原理:首先调用登录,会传递一个token给前端,之后的接口都需要用到这个token,需要前端将token放入请求头里面,在调接口的时候传过来,后端获取到了这个token后,将获取的token与数据库中的比对,相同则说明已登录,可以调用接口。
实现解析:
1、首先需要登录,需要生成一个token,并且token要存入数据库,token怎么存?
考虑到这个token基本不会变并且使用频繁,因此存储到redis中是一个不错的选择,后面请求头中token都与redis中的进行比对,想要在redis中找到这个token,因此需要不同的key来标识不同的token,例如token1:"12345",token2:"23456",因此需要定义一个容易找的标识,我使用的是cache_具体的token值这种格式。
2、第二个问题,在每个接口之前都写上一个获取token的方法判断吗?
这种方式肯定是不可取的,接口如果多起来了,会很麻烦,因此我用到了spring的AOP面向切面编程,就是在controller中的每个接口之前建了一个切面,在这个切面统一执行一个方法,去判断token,这样可以统一的管理,不需要去重复写代码判断,在这里我们不要忘记去过滤登录的接口,那个接口不需要token。
3、如果用户长时间未操作,为了安全考虑,token需要自动销毁,如何做呢,定时任务吗?
类似与定时任务,redis可以给里面的数据设置一个存活时间,到了时间会自动删除,但是为了用户的体验,因此需要在每次调接口的时候,刷新一遍存活时间,这样可以优化用户的体验。
主要实现代码如下:
//建立切点
@pointcut("execution(* com.example.blog.controller.*.*(..))")
public void controllerMethod(){}
@Before("controllerMethod()")
public void LogRequestInfo(JoinPoint joinPoint){
RequestAttributes requestAttribute = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes)requestAttribute).getRequest();
// 打印请求内容
log.info("----------------------------------------------------------接口调用发起----------------------------------------------------------");
log.info("接收到请求,请求方式={},请求地址={},请求IP={},请求方法名称={},请求参数={}",request.getmethod(),request.getRequestURL().toString(),
ToolsUtil.getServerIp(),joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
//过滤登录接口
if(!joinPoint.getSignature().getName().equals("userLogin")){
//接口之前,权限校验
String key = "cache_token_"+ RequestUtil.getUserId();
if(ParamUtil.empty(redisUtil.get(key))){
log.info("接口调用失败:返回结果=" + ResponseCode.NoAuthor.toString());
log.info("----------------------------------------------------------接口调用结束----------------------------------------------------------");
throw new CommonException(ResponseCode.NoAuthor.getMessage(),ResponseCode.NoAuthor.getMessage_en(),ResponseCode.NoAuthor.getErrorCode());
}
if(!Objects.equals(RequestUtil.getToken(), redisUtil.get(key))){
log.info("接口调用失败:返回结果=" + ResponseCode.nopOWER.toString());
log.info("----------------------------------------------------------接口调用结束----------------------------------------------------------");
throw new CommonException(ResponseCode.nopOWER.getMessage(),ResponseCode.nopOWER.getMessage_en(),ResponseCode.nopOWER.getErrorCode());
}
//刷新token存活时间
redisUtil.expire(key,4*60*60);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。