token登录+redis缓存

token登录

1.用户登录

    /**
     * 用户登录
     * @param user
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public Result userLogin(@RequestBody User user, HttpServletResponse response,HttpServletRequest request) {
        log.info("用户登录[start]");
        String authToken = request.getHeader(Constants.RESPONSE_TOKEN);
        if(!StringUtils.isBlank(authToken)){
            TokenAuthBO tokenBo = tokenService.verifyToken(authToken);
            if(tokenBo.isAuthState()){
                return new Result(Result.SUCCESS_CODE, "你已经登录,无需重复登录!");
            }
        }

        if (StringUtils.isBlank(user.getUserName()) || StringUtils.isBlank(user.getUserPass())) {
            log.info("无效参数");
            return new Result(Result.ERROR_CODE, "无效参数!");
        }
        int count = loginService.checkUserName(user.getUserName());
        //是否存在用户
        if (count == 0) {
            log.info("没有该用户");
            return new Result(Result.ERROR_CODE, "没有该用户!");
        }

        User u = loginService.userLogin(user);
        if (u == null) {
            log.info("用户登失败,密码错误");
            return new Result(Result.ERROR_CODE, "密码错误!");
        }
        //用户状态为启用
        if (u.getUserStartusing() == 1) {
            log.info("用户登失败,账号禁止使用");
            return new Result(Result.ERROR_CODE, "账号禁止使用!");
        }
        // 生成Token
        Integer userId =  u.getUserId();
        Long loginTime = System.currentTimeMillis() / 1000;
        long  changePwdTime = loginTime;
        String token = tokenService.createToken(userId, loginTime, changePwdTime);
        //设置响应token
        Cookie cookie = new Cookie(Constants.RESPONSE_TOKEN,token);
        cookie.setHttpOnly(false);
        cookie.setPath("/");
        cookie.setMaxAge(60 * 60 * 24 ); //有效期一天
        response.addCookie(cookie);
        //存入缓存
        template.opsForValue().set(token,user,1, TimeUnit.DAYS);
        log.info("用户登录[end]");
        return new Result(Result.SUCCESS_CODE, "登陆成功!",template.opsForValue().get(token));
    }

2.生成token

	/**
	 * @author sxw 创建Token
	 * @param userId 用户Id, loginTime登录时间, changePwdTime密码修改时间
	 * @return TokenAuthEnum 认证result枚举
	 **/
	public String createToken(Integer userId, Long loginTime, Long changePwdTime) {
		log.info("创建Token[start], userId: " + userId + ", loginTime: " + loginTime + ", changePwdTime: "
				+ changePwdTime);
		JSONObject tokenJson = new JSONObject();
		tokenJson.put(TOKEN_USERID, userId);
		tokenJson.put(TOKEN_LOGIN_TIME, loginTime);
		tokenJson.put(TOKEN_CHANGE_PWD_TIME, changePwdTime);
		long endTime = loginTime + 72*60*60;
		tokenJson.put(TOKEN_END_TIME, endTime);
		String encryptToken = DESUtils.encrypt(tokenJson.toJSONString());
		String token = Base64.encodeBase64URLSafeString(encryptToken.getBytes());
		log.info("创建Token[end], token: " + token);
		return token;
	}

3.校验token

	/**
	 * @author sxw 验证Token
	 * @param token 认证字符
	 * @return TokenAuthEnum 认证result枚举
	 **/
	public TokenAuthBO verifyToken(String token) {
		log.info("token认证开始[start], token: " + token);
		if (StringUtils.isBlank(token)) {
			log.warn("token认证开始[end], token is null~");
			return new TokenAuthBO(TokenAuthEnum.FAIL_ISNULL, Collections.emptyMap());
		}

		JSONObject tokenJson = null;
		try {
			String base64Token = new String(Base64.decodeBase64(token));
			String decrypt = DESUtils.decrypt(base64Token);
			tokenJson = JSONObject.parseObject(decrypt);
			log.info("token解析后的数据,tokenJson: " + tokenJson);
			if (MapUtils.isBlank(tokenJson) || tokenJson.isEmpty()) {
				throw new SecurityException("tokenJson is NULL");
			}
			tokenJson.put(TOKEN, token);
		} catch (SecurityException | JSONException ex) {
			log.error("token 解析解密异常,message: " + ex.getMessage());
			return new TokenAuthBO(TokenAuthEnum.FAIL, Collections.emptyMap());
		}

		if (MapUtils.isEmptyMap(tokenJson,
				new String[] { TOKEN_USERID, TOKEN_LOGIN_TIME, TOKEN_END_TIME, TOKEN_CHANGE_PWD_TIME })) {
			log.warn("token缺失数据~");
			return new TokenAuthBO(TokenAuthEnum.FAIL_DATA_ERROR, tokenJson);
		}

		if (!StringUtils.isNumeric(tokenJson.getString(TOKEN_USERID))
				|| !StringUtils.isNumeric(tokenJson.getString(TOKEN_LOGIN_TIME))
				|| !StringUtils.isNumeric(tokenJson.getString(TOKEN_END_TIME))
				|| !StringUtils.isNumeric(tokenJson.getString(TOKEN_CHANGE_PWD_TIME))) {
			log.warn("token数据格式有误~");
			return new TokenAuthBO(TokenAuthEnum.FAIL_DATA_ERROR, tokenJson);
		}

		Integer loginTime = Integer.parseInt(tokenJson.getString(TOKEN_LOGIN_TIME));
		Integer endTime = Integer.parseInt(tokenJson.getString(TOKEN_END_TIME));
		Integer change_pwd_time = Integer.parseInt(tokenJson.getString(TOKEN_CHANGE_PWD_TIME));

		// 判断token时间有效性
		long thisTime = System.currentTimeMillis() / 1000;
		if (!(thisTime >= loginTime && thisTime <= endTime)) {
			log.warn("token timeOut, token解析后的数据,tokenJson: " + tokenJson + ", thisTime: " + thisTime);
			return new TokenAuthBO(TokenAuthEnum.FAIL_TIMEOUT, tokenJson);
		}

		// 判断userId有效性
		String userId = tokenJson.getString(TOKEN_USERID);
		Map<String,Object> data = tokenDao.getObjectByUserId(userId);
		String newChangeTime = data.get("pwdChangeTime").toString();
		Integer num = (Integer) data.get("num");
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = null;
		try {
			date = simpleDateFormat.parse(newChangeTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		long newChangeTimeNow =   date.getTime()/1000;
		if (num == 0) {
			log.warn("认证失败,非有效用户~");
			return new TokenAuthBO(TokenAuthEnum.FAIL, tokenJson);
		}

		// 判断密码最新修改时间是否大于token中历史修改时间
		if (newChangeTimeNow > change_pwd_time.intValue()) {
			log.warn("认证成功,密码已过期[密码修改时间: " + newChangeTimeNow + "], token密码时间: " + change_pwd_time);
			return new TokenAuthBO(TokenAuthEnum.FAIL_PWDCHANGE, tokenJson);
		}
		Object user = template.opsForValue().get(token);
		if(user == null){
			log.warn("redis已过期,请更新redis");
			return new TokenAuthBO(TokenAuthEnum.FAIL_PWDCHANGE, tokenJson);
		}
		log.info("token认证成功 \n"+"token="+token+"\n"+"tokenInfo="+tokenJson);
		return new TokenAuthBO(TokenAuthEnum.SUCCESS, tokenJson);
	}

4.yml配置redis

  redis:
    database: 0
    host: localhost
    jedis:
      pool:
        max-active: 8
        max-idle: 8
        max-wait: -1ms
        min-idle: 0
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        max-wait: -1ms
        min-idle: 0
      shutdown-timeout: 100ms
    password: 123456
    port: 6379

5.pom.xml配置

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-json</artifactId>
        </dependency>

6.redis序列化

@Configuration
public class RedisConfig {

    //还是使用springboot默认配置的RedisConnectionFactory
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    // 默认用的是用JdkSerializationRedisSerializer进行序列化的
    @Bean
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        // 注入数据源
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 使用Jackson2JsonRedisSerialize 替换默认序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key-value结构序列化数据结构
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // hash数据结构序列化方式,必须这样否则存hash 就是基于jdk序列化的
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        // 启用默认序列化方式
        redisTemplate.setEnableDefaultSerializer(true);
        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);

        /// redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}
  • 8
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值