项目中使用shrio,如何获取当前用户信息

33、项目中使用shrio,如何获取当前用户信息

原理:直接从当前线程里面拿到subject,前台每一次请求的话,都是要走拦截器的,根据前台传回的cookie,通过shrio的 SessionManager 去获取到对应的seesionid,然后再绑定到线程上,即每个shiro拦截到的请求之后,重新获取到seesionid, 然后根据seesionid创建Subject,清除当前线程的绑定,然后重新绑定的线程中,之后执行过滤器。所以我们再SecurityUtils.getSubject()中获取的一直是当前用户的信息。

使用shiro时,如果正常登陆(执行subject.login(token)成功)就能在全局通过SecurityUtils.getSubject().getPrincipal()获取用户信息。

LoginUser userNow=(LoginUser) SecurityUtils.getSubject().getPrincipal();

返回的是Loginuser 是因为我们在登录的时候,已经设置了

/**
    * 用户信息认证是在用户进行登录的时候进行验证(不存redis)
 * 也就是说验证用户输入的账号和密码是否正确,错误抛出异常
 *
 * @param auth 用户登录的账号密码信息
 * @return 返回封装了用户信息的 AuthenticationInfo 实例
    * @throws AuthenticationException
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
   String token = (String) auth.getCredentials();
   if (token == null) {
      log.info("————————身份认证失败——————————IP地址:  "+ ObjectConvertUtils.getIpAddrByRequest(SpringContextUtils.getHttpServletRequest()));
      throw new AuthenticationException("token为空!");
   }
   // 校验token有效性
   LoginUser loginUser = this.checkUserTokenIsEffect(token);
   return new SimpleAuthenticationInfo(loginUser, token, getName());
}

/**
 * 校验token的有效性
 *
 * @param token
 */
public LoginUser checkUserTokenIsEffect(String token) throws AuthenticationException {
   // 解密获得username,用于和数据库进行对比
   String username = JwtUtil.getUsername(token);
   if (username == null) {
      throw new AuthenticationException("token非法无效!");
   }

   // 查询用户信息
   log.info("———校验token是否有效————checkUserTokenIsEffect——————— "+ token);
       LoginUser loginUser = sysBaseAPI.getUserByName(username);
   if (loginUser == null) {
      throw new AuthenticationException("用户不存在!");
   }
       // 判断用户状态
       if (loginUser.getStatus().equals(CommonConstant.USER_FREEZE.toString())) {
           throw new AuthenticationException("账号已被锁定,请联系管理员!");
       }
   // 校验token是否超时失效 & 或者账号密码是否错误
   if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {
      throw new AuthenticationException("Token失效,请重新登录!");
   }

   return loginUser;
}

/**
 * JWTToken刷新生命周期 (实现: 用户在线操作不掉线功能)
 * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样),缓存有效期设置为Jwt有效时间的2倍
 * 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
 * 3、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算
 * 4、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。
 * 注意: 前端请求Header中设置Authorization保持不变,校验有效性以缓存中的token为准。
    *       用户过期时间 = Jwt有效时间 * 2。
 *
 * @param userName
 * @param passWord
 * @return
 */
public boolean jwtTokenRefresh(String token, String userName, String passWord) {
   String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
   if (ObjectConvertUtils.isNotEmpty(cacheToken)) {
      // 校验token有效性
      if (!JwtUtil.verify(cacheToken, userName, passWord)) {
         String newAuthorization = JwtUtil.sign(userName, passWord);
         // 设置超时时间
         redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
         redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME *2 / 1000);
               log.info("——————————用户在线操作,更新token保证不掉线—————————jwtTokenRefresh——————— "+ token);
      }
      return true;
   }
   return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值