SprigBoot + JWT + Redis 实现单点登录功能实现

為{幸葍}努か 提交于 2020-03-22 22:42:26

3 月,跳不动了?>>>

基于  SprigBoot + JWT + Redis 实现单点登录思路 实现. 代码如下

返回Token:  userid + md5盐 + 当前日期

调用token:  JWT_TOKEN


1. 如果token部分 携带日期 大于 当前日期, 此时为被挤下线;

2. 如果token部分 Redis 没有查找到,

拦截器部分: 

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		if (handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			Method method = handlerMethod.getMethod();
			NoAuth noAuth = AnnotationUtils.findAnnotation(method, NoAuth.class);

			String authorization = request.getHeader("Authorization");
			// 需要登录
			if (noAuth == null) {
				if (null == authorization) {
					throw new ServiceException(Result.NOT_LOGIN, "请登录后再操作");
				}

				//2. 查看token是否被踢下线
				String loginTimer = authorization.substring(39);
				log.info("token是否过期:{}" , (System.currentTimeMillis() - Long.valueOf(loginTimer)) < JwtConstant.REDIS_TIME_S);
				if((System.currentTimeMillis() - Long.valueOf(loginTimer)) < JwtConstant.REDIS_TIME_S){
					String userToken = authorization.substring(7);
					//3. 如果token不存在就是被挤下线了
					if(redisUtils.hasKey(RedisConstant.redisNamePre + userToken)){
						long time = redisUtils.getExpire(RedisConstant.redisNamePre+userToken);
						//如果 token 小于 10分钟就续费 30 分钟
						if(time < 300){
							redisUtils.expire(RedisConstant.redisNamePre+userToken , time + JwtConstant.REDIS_TIME);
						}
					}else{
						throw new ServiceException(10004 , "被踢下线喽.......");
					}
				}
				throw new ServiceException(10003 , "TOKEN过期喽.......");
			}
			return true;
		}
		return false;
	}

登录部分:

@ApiOperation("用户登录")
    @NoAuth
    @PostMapping("/auth/login")
    public Result<String> userLogin(HttpServletRequest request, UserLoginDTO user) throws Exception {
        TUtil.checkObj(new String[]{"用户名不能为空", "密码不能为空"}, user.getPhone(), user.getPassword());

        String passwd = DigestUtil.md5Hex(user.getPassword() + JwtConstant.MD5_KEY);
        user.setPassword(passwd);
        TUser tUser = userService.userToken(user);
        if(tUser != null){
            //获取用户设备
            String uaStr = request.getHeader("User-Agent");
            UserAgent ua = UserAgentUtil.parse(uaStr);

            //1. 创建token数据
            JwtToken token = new JwtToken();
            token.setUserId(tUser.getId());
            token.setCellPhone(tUser.getPhone());
            token.setDevice(ua.getOs().toString());
            String ip = StringUtils.getIp(request);
            String ipInfo = StringUtils.getCityInfo(ip);
            token.setIp(ip);
            token.setIpInfo(ipInfo);

            //2. 生成JWT TOKEN
            String tokenStr = JwtUtils.createToken(token);
            //创建TokenName: userid + md5盐 + 当前日期
            String tokenName = DigestUtil.md5Hex(tUser.getId()+JwtConstant.MD5_KEY+DateUtil.yyyyMMdd.format(new Date())).toUpperCase();

            //3.删除redis数据
            redisUtils.delKeys(RedisConstant.redisNamePre + tokenName);
            //4. 写入缓存
            Map<String, Object> map = new HashMap<String, Object>(2);
            map.put("loginTimer" , System.currentTimeMillis());
            map.put("token" , tokenStr);
            String authToken = tokenName + System.currentTimeMillis();
            redisUtils.hmset(RedisConstant.redisNamePre + authToken, map, JwtConstant.REDIS_TIME);

            log.info("用户: {} 登录成功,设备: {}" , user.getPhone(), token.getDevice());
            return Result.initSuccessResult(authToken);
        }
        return Result.initFailureResult(10001, "用户名或密码错误");
    }

以上为实现的主要功能部分

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!