yumeng пре 5 година
родитељ
комит
b33806a94a

+ 125 - 124
jeecg-boot-module-system/src/main/java/org/jeecg/modules/shiro/authc/ShiroRealm.java

@@ -34,129 +34,130 @@ import lombok.extern.slf4j.Slf4j;
 @Slf4j
 public class ShiroRealm extends AuthorizingRealm {
 
-	@Autowired
-	@Lazy
-	private ISysUserService sysUserService;
-	@Autowired
-	@Lazy
-	private RedisUtil redisUtil;
-
-	/**
-	 * 必须重写此方法,不然Shiro会报错
-	 */
-	@Override
-	public boolean supports(AuthenticationToken token) {
-		return token instanceof JwtToken;
-	}
-
-	/**
-	 * 功能: 获取用户权限信息,包括角色以及权限。只有当触发检测用户权限时才会调用此方法,例如checkRole,checkPermission
-	 *
-	 * @return AuthorizationInfo 权限信息
-	 */
-	@Override
-	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
-		log.info("————权限认证 [ roles、permissions]————");
-		LoginUser sysUser = null;
-		String username = null;
-		if (principals != null) {
-			sysUser = (LoginUser) principals.getPrimaryPrincipal();
-			username = sysUser.getUsername();
-		}
-		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
-
-		// 设置用户拥有的角色集合,比如“admin,test”
-		Set<String> roleSet = sysUserService.getUserRolesSet(username);
-		info.setRoles(roleSet);
-
-		// 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add”
-		Set<String> permissionSet = sysUserService.getUserPermissionsSet(username);
-		info.addStringPermissions(permissionSet);
-		return info;
-	}
-
-	/**
-	 * 功能: 用来进行身份认证,也就是说验证用户输入的账号和密码是否正确,获取身份验证信息,错误抛出异常
-	 *
-	 * @param auth 用户身份信息 token
-	 * @return 返回封装了用户信息的 AuthenticationInfo 实例
-	 */
-	@Override
-	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
-		log.debug("————身份认证————");
-		String token = (String) auth.getCredentials();
-		if (token == null) {
-			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非法无效!");
-		}
-
-		// 查询用户信息
-		LoginUser loginUser = new LoginUser();
-		SysUser sysUser = sysUserService.getUserByName(username);
-		if (sysUser == null) {
-			throw new AuthenticationException("用户不存在!");
-		}
-
-		// 校验token是否超时失效 & 或者账号密码是否错误
-		if (!jwtTokenRefresh(token, username, sysUser.getPassword())) {
-			throw new AuthenticationException("Token失效,请重新登录!");
-		}
-
-		// 判断用户状态
-		if (sysUser.getStatus() != 1) {
-			throw new AuthenticationException("账号已被锁定,请联系管理员!");
-		}
-		BeanUtils.copyProperties(sysUser, loginUser);
-		return loginUser;
-	}
-
-	/**
-	 * JWTToken刷新生命周期 (解决用户一直在线操作,提供Token失效问题)
-	 * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样)
-	 * 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
-	 * 3、当该用户这次请求JWTToken值还在生命周期内,则会通过重新PUT的方式k、v都为Token值,缓存中的token值生命周期时间重新计算(这时候k、v值一样)
-	 * 4、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算
-	 * 5、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。
-	 * 6、每次当返回为true情况下,都会给Response的Header中设置Authorization,该Authorization映射的v为cache对应的v值。
-	 * 7、注:当前端接收到Response的Header中的Authorization值会存储起来,作为以后请求token使用
-	 * 参考方案:https://blog.csdn.net/qq394829044/article/details/82763936
-	 * 
-	 * @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 (oConvertUtils.isNotEmpty(cacheToken)) {
-			// 校验token有效性
-			if (!JwtUtil.verify(token, 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 / 1000);
-			} else {
-				redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
-				// 设置超时时间
-				redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
-			}
-			return true;
-		}
-		return false;
-	}
+    @Autowired
+    @Lazy
+    private ISysUserService sysUserService;
+    @Autowired
+    @Lazy
+    private RedisUtil redisUtil;
+
+    /**
+     * 必须重写此方法,不然Shiro会报错
+     */
+    @Override
+    public boolean supports(AuthenticationToken token) {
+        return token instanceof JwtToken;
+    }
+
+    /**
+     * 功能: 获取用户权限信息,包括角色以及权限。只有当触发检测用户权限时才会调用此方法,例如checkRole,checkPermission
+     *
+     * @return AuthorizationInfo 权限信息
+     */
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+        log.info("————权限认证 [ roles、permissions]————");
+        LoginUser sysUser = null;
+        String username = null;
+        if (principals != null) {
+            sysUser = (LoginUser) principals.getPrimaryPrincipal();
+            username = sysUser.getUsername();
+        }
+        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+
+        // 设置用户拥有的角色集合,比如“admin,test”
+        Set<String> roleSet = sysUserService.getUserRolesSet(username);
+        info.setRoles(roleSet);
+
+        // 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add”
+        Set<String> permissionSet = sysUserService.getUserPermissionsSet(username);
+        info.addStringPermissions(permissionSet);
+        return info;
+    }
+
+    /**
+     * 功能: 用来进行身份认证,也就是说验证用户输入的账号和密码是否正确,获取身份验证信息,错误抛出异常
+     *
+     * @param auth 用户身份信息 token
+     * @return 返回封装了用户信息的 AuthenticationInfo 实例
+     */
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
+        log.debug("————身份认证————");
+        String token = (String) auth.getCredentials();
+        if (token == null) {
+            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非法无效!");
+        }
+
+        // 查询用户信息
+        LoginUser loginUser = new LoginUser();
+        SysUser sysUser = sysUserService.getUserByName(username);
+        if (sysUser == null) {
+            throw new AuthenticationException("用户不存在!");
+        }
+
+        // 校验token是否超时失效 & 或者账号密码是否错误
+        if (!jwtTokenRefresh(token, username, sysUser.getPassword())) {
+            // throw new AuthenticationException("Token失效,请重新登录!");
+            log.error("Token失效,请重新登录!");
+        }
+
+        // 判断用户状态
+        if (sysUser.getStatus() != 1) {
+            throw new AuthenticationException("账号已被锁定,请联系管理员!");
+        }
+        BeanUtils.copyProperties(sysUser, loginUser);
+        return loginUser;
+    }
+
+    /**
+     * JWTToken刷新生命周期 (解决用户一直在线操作,提供Token失效问题)
+     * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样)
+     * 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
+     * 3、当该用户这次请求JWTToken值还在生命周期内,则会通过重新PUT的方式k、v都为Token值,缓存中的token值生命周期时间重新计算(这时候k、v值一样)
+     * 4、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算
+     * 5、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。
+     * 6、每次当返回为true情况下,都会给Response的Header中设置Authorization,该Authorization映射的v为cache对应的v值。
+     * 7、注:当前端接收到Response的Header中的Authorization值会存储起来,作为以后请求token使用
+     * 参考方案:https://blog.csdn.net/qq394829044/article/details/82763936
+     *
+     * @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 (oConvertUtils.isNotEmpty(cacheToken)) {
+            // 校验token有效性
+            if (!JwtUtil.verify(token, 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 / 1000);
+            } else {
+                redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
+                // 设置超时时间
+                redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
+            }
+            return true;
+        }
+        return false;
+    }
 
 }