diff --git a/config/dev/application.yml b/config/dev/application.yml index 313c2ec29..58609d210 100644 --- a/config/dev/application.yml +++ b/config/dev/application.yml @@ -152,6 +152,37 @@ logging: com.alibaba.nacos: warn config: classpath:logback.xml +# Sa-Token配置 +sa-token: + # token名称 (同时也是cookie名称) + token-name: Authorization + # token有效期 设为一天 (必定过期) 单位: 秒 + timeout: 86400 + # token临时有效期 (指定时间无操作就过期) 单位: 秒 + activity-timeout: 1800 + # 开启内网服务调用鉴权 + check-id-token: true + # Id-Token的有效期 (单位: 秒) + id-token-timeout: 600 + # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) + is-share: false + # 是否尝试从请求体里读取token + is-read-body: false + # 是否尝试从header里读取token + is-read-head: true + # 是否尝试从cookie里读取token + is-read-cookie: false + # token前缀 + token-prefix: "Bearer" + # token风格 + token-style: uuid + # jwt秘钥 + jwt-secret-key: abcdefghijklmnopqrstuvwxyz + # 是否输出操作日志 + is-log: true + # MyBatisPlus配置 # https://baomidou.com/config/ mybatis-plus: diff --git a/config/dev/ruoyi-gateway.yml b/config/dev/ruoyi-gateway.yml index b9db83882..c00542b1d 100644 --- a/config/dev/ruoyi-gateway.yml +++ b/config/dev/ruoyi-gateway.yml @@ -20,6 +20,7 @@ security: # 不校验白名单 ignore: whites: + - /code - /auth/logout - /auth/login - /auth/register diff --git a/pom.xml b/pom.xml index 563a9f6bf..ec5bc5f9a 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ 2.3.0 2.0.9 3.0.3 + 1.28.0 localhost @@ -273,13 +274,6 @@ ${commons-collections.version} - - - com.alibaba - transmittable-thread-local - ${transmittable-thread-local.version} - - org.redisson diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteDataScopeService.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteDataScopeService.java new file mode 100644 index 000000000..a8664f70e --- /dev/null +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteDataScopeService.java @@ -0,0 +1,20 @@ +package com.ruoyi.system.api; + +/** + * 数据权限服务 + * + * @author Lion Li + */ +public interface RemoteDataScopeService { + + /** + * 获取角色自定义权限语句 + */ + String getRoleCustom(Long roleId); + + /** + * 获取部门和下级权限语句 + */ + String getDeptAndChild(Long deptId); + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUserOnline.java similarity index 90% rename from ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java rename to ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUserOnline.java index 10b80bf97..6d76c59e7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUserOnline.java @@ -1,10 +1,12 @@ -package com.ruoyi.system.domain; +package com.ruoyi.system.api.domain; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.NoArgsConstructor; +import java.io.Serializable; + /** * 当前在线会话 * @@ -14,7 +16,7 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @ApiModel("当前在线会话业务对象") -public class SysUserOnline { +public class SysUserOnline implements Serializable { /** * 会话编号 diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java index e43ca19b8..facb66bc0 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java @@ -1,11 +1,12 @@ package com.ruoyi.system.api.model; -import com.ruoyi.system.api.domain.SysUser; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ruoyi.common.core.constant.CacheConstants; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; import java.io.Serializable; +import java.util.List; import java.util.Set; /** @@ -18,20 +19,30 @@ import java.util.Set; public class LoginUser implements Serializable { private static final long serialVersionUID = 1L; + /** + * 用户ID + */ + private Long userId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 部门名 + */ + private String deptName; + /** * 用户唯一标识 */ private String token; /** - * 用户名id + * 用户类型 */ - private Long userid; - - /** - * 用户名 - */ - private String username; + private String userType; /** * 登录时间 @@ -49,18 +60,56 @@ public class LoginUser implements Serializable { private String ipaddr; /** - * 权限列表 + * 登录地点 */ - private Set permissions; + private String loginLocation; /** - * 角色列表 + * 浏览器类型 */ - private Set roles; + private String browser; /** - * 用户信息 + * 操作系统 */ - private SysUser sysUser; + private String os; + + /** + * 菜单权限 + */ + private Set menuPermission; + + /** + * 角色权限 + */ + private Set rolePermission; + + /** + * 用户名 + */ + private String username; + + /** + * 密码 + */ + @JsonIgnore + private String password; + + /** + * 角色对象 + */ + private List roles; + + /** + * 数据权限 当前角色ID + */ + private Long roleId; + + /** + * 获取登录id + */ + public String getLoginId() { + return userType + CacheConstants.LOGINID_JOIN_CODE + userId; + } } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/RoleDTO.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/RoleDTO.java new file mode 100644 index 000000000..13592dc57 --- /dev/null +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/RoleDTO.java @@ -0,0 +1,38 @@ +package com.ruoyi.system.api.model; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 角色 + * + * @author Lion Li + */ + +@Data +@NoArgsConstructor +public class RoleDTO implements Serializable { + + /** + * 角色ID + */ + private Long roleId; + + /** + * 角色名称 + */ + private String roleName; + + /** + * 角色权限 + */ + private String roleKey; + + /** + * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) + */ + private String dataScope; + +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java index c90a2ce6f..febd0d658 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java @@ -1,24 +1,23 @@ package com.ruoyi.auth.controller; -import cn.hutool.core.util.ObjectUtil; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; import com.ruoyi.auth.form.LoginBody; import com.ruoyi.auth.form.RegisterBody; import com.ruoyi.auth.service.SysLoginService; import com.ruoyi.common.core.domain.R; -import com.ruoyi.common.core.utils.JwtUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.security.auth.AuthUtil; -import com.ruoyi.common.security.service.TokenService; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.core.enums.DeviceType; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.model.LoginUser; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; /** * token 控制 @@ -29,7 +28,6 @@ import javax.servlet.http.HttpServletRequest; @RestController public class TokenController { - private final TokenService tokenService; private final SysLoginService sysLoginService; @PostMapping("login") @@ -37,29 +35,18 @@ public class TokenController { // 用户登录 LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword()); // 获取登录token - return R.ok(tokenService.createToken(userInfo)); + LoginHelper.loginByDevice(userInfo, DeviceType.PC); + // 接口返回信息 + Map rspMap = new HashMap(); + rspMap.put("access_token", StpUtil.getTokenValue()); + return R.ok(rspMap); } @DeleteMapping("logout") public R logout(HttpServletRequest request) { - String token = SecurityUtils.getToken(request); - if (StringUtils.isNotEmpty(token)) { - String username = JwtUtils.getUserName(token); - // 删除用户缓存记录 - AuthUtil.logoutByToken(token); - // 记录用户退出日志 - sysLoginService.logout(username); - } - return R.ok(); - } - - @PostMapping("refresh") - public R refresh(HttpServletRequest request) { - LoginUser loginUser = tokenService.getLoginUser(request); - if (ObjectUtil.isNotNull(loginUser)) { - // 刷新令牌有效期 - tokenService.refreshToken(loginUser); - return R.ok(); + try { + StpUtil.logout(); + } catch (NotLoginException e) { } return R.ok(); } diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/listener/UserActionListener.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/listener/UserActionListener.java new file mode 100644 index 000000000..174d2c070 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/listener/UserActionListener.java @@ -0,0 +1,121 @@ +package com.ruoyi.auth.listener; + +import cn.dev33.satoken.config.SaTokenConfig; +import cn.dev33.satoken.listener.SaTokenListener; +import cn.dev33.satoken.stp.SaLoginModel; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import com.ruoyi.common.core.constant.CacheConstants; +import com.ruoyi.common.core.enums.UserType; +import com.ruoyi.common.core.utils.ServletUtils; +import com.ruoyi.common.core.utils.ip.AddressUtils; +import com.ruoyi.common.redis.utils.RedisUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; +import com.ruoyi.system.api.domain.SysUserOnline; +import com.ruoyi.system.api.model.LoginUser; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.concurrent.TimeUnit; + +/** + * 用户行为 侦听器的实现 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Component +@Slf4j +public class UserActionListener implements SaTokenListener { + + private final SaTokenConfig tokenConfig; + + /** + * 每次登录时触发 + */ + @Override + public void doLogin(String loginType, Object loginId, SaLoginModel loginModel) { + UserType userType = UserType.getUserType(loginId.toString()); + if (userType == UserType.SYS_USER) { + UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = ServletUtils.getClientIP(); + LoginUser user = LoginHelper.getLoginUser(); + String tokenValue = StpUtil.getTokenValue(); + SysUserOnline userOnline = new SysUserOnline(); + userOnline.setIpaddr(ip); + userOnline.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + userOnline.setBrowser(userAgent.getBrowser().getName()); + userOnline.setOs(userAgent.getOs().getName()); + userOnline.setLoginTime(System.currentTimeMillis()); + userOnline.setTokenId(tokenValue); + userOnline.setUserName(user.getUsername()); + if (ObjectUtil.isNotNull(user.getDeptName())) { + userOnline.setDeptName(user.getDeptName()); + } + RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline, tokenConfig.getTimeout(), TimeUnit.SECONDS); + log.info("user doLogin, useId:{}, token:{}", loginId, tokenValue); + } else if (userType == UserType.APP_USER) { + // app端 自行根据业务编写 + } + } + + /** + * 每次注销时触发 + */ + @Override + public void doLogout(String loginType, Object loginId, String tokenValue) { + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); + log.info("user doLogout, useId:{}, token:{}", loginId, tokenValue); + } + + /** + * 每次被踢下线时触发 + */ + @Override + public void doKickout(String loginType, Object loginId, String tokenValue) { + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); + log.info("user doLogoutByLoginId, useId:{}, token:{}", loginId, tokenValue); + } + + /** + * 每次被顶下线时触发 + */ + @Override + public void doReplaced(String loginType, Object loginId, String tokenValue) { + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); + log.info("user doReplaced, useId:{}, token:{}", loginId, tokenValue); + } + + /** + * 每次被封禁时触发 + */ + @Override + public void doDisable(String loginType, Object loginId, long disableTime) { + } + + /** + * 每次被解封时触发 + */ + @Override + public void doUntieDisable(String loginType, Object loginId) { + } + + /** + * 每次创建Session时触发 + */ + @Override + public void doCreateSession(String id) { + } + + /** + * 每次注销Session时触发 + */ + @Override + public void doLogoutSession(String id) { + } + + +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java index b7b3bcb1e..6f33d570c 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java @@ -1,12 +1,14 @@ package com.ruoyi.auth.service; import cn.hutool.core.util.ObjectUtil; +import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.enums.UserStatus; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.redis.utils.RedisUtils; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.system.api.RemoteLogService; import com.ruoyi.system.api.RemoteUserService; @@ -16,6 +18,8 @@ import com.ruoyi.system.api.model.LoginUser; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.stereotype.Service; +import java.util.concurrent.TimeUnit; + /** * 登录校验方法 * @@ -40,36 +44,58 @@ public class SysLoginService { } // 密码如果不在指定范围内 错误 if (password.length() < UserConstants.PASSWORD_MIN_LENGTH - || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"); throw new ServiceException("用户密码不在指定范围"); } // 用户名不在指定范围内 错误 if (username.length() < UserConstants.USERNAME_MIN_LENGTH - || username.length() > UserConstants.USERNAME_MAX_LENGTH) { + || username.length() > UserConstants.USERNAME_MAX_LENGTH) { recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围"); throw new ServiceException("用户名不在指定范围"); } - // 查询用户信息 - LoginUser userInfo = remoteUserService.getUserInfo(username); + LoginUser userInfo; + try { + // 查询用户信息 + userInfo = remoteUserService.getUserInfo(username); - if (ObjectUtil.isNull(userInfo)) { - recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); - throw new ServiceException("登录用户:" + username + " 不存在"); + if (ObjectUtil.isNull(userInfo)) { + recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); + throw new ServiceException("登录用户:" + username + " 不存在"); + } + } catch (Exception e) { + recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()); + throw new ServiceException(e.getMessage()); } - SysUser user = userInfo.getSysUser(); - if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { - recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); - throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + + // 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip) + Integer errorNumber = RedisUtils.getCacheObject(CacheConstants.LOGIN_ERROR + username); + // 锁定时间内登录 则踢出 + if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(CacheConstants.LOGIN_ERROR_NUMBER)) { + String msg = "密码错误次数过多,帐户锁定" + CacheConstants.LOGIN_ERROR_LIMIT_TIME + "分钟"; + recordLogininfor(username, Constants.LOGIN_FAIL, msg); + throw new ServiceException(msg, null); } - if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { - recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); - throw new ServiceException("对不起,您的账号:" + username + " 已停用"); - } - if (!SecurityUtils.matchesPassword(password, user.getPassword())) { - recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误"); - throw new ServiceException("用户不存在/密码错误"); + + if (!SecurityUtils.matchesPassword(password, userInfo.getPassword())) { + // 是否第一次 + errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1; + // 达到规定错误次数 则锁定登录 + if (errorNumber.equals(CacheConstants.LOGIN_ERROR_NUMBER)) { + String msg = "密码错误次数过多,帐户锁定" + CacheConstants.LOGIN_ERROR_LIMIT_TIME + "分钟"; + RedisUtils.setCacheObject(CacheConstants.LOGIN_ERROR + username, errorNumber, CacheConstants.LOGIN_ERROR_LIMIT_TIME, TimeUnit.MINUTES); + recordLogininfor(username, Constants.LOGIN_FAIL, msg); + throw new ServiceException(msg, null); + } else { + // 未达到规定错误次数 则递增 + String msg = "密码输入错误" + errorNumber + "次"; + RedisUtils.setCacheObject(CacheConstants.LOGIN_ERROR + username, errorNumber); + recordLogininfor(username, Constants.LOGIN_FAIL, msg); + throw new ServiceException(msg, null); + } } + // 登录成功 清空错误次数 + RedisUtils.deleteObject(CacheConstants.LOGIN_ERROR + username); recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); return userInfo; } @@ -87,11 +113,11 @@ public class SysLoginService { throw new ServiceException("用户/密码必须填写"); } if (username.length() < UserConstants.USERNAME_MIN_LENGTH - || username.length() > UserConstants.USERNAME_MAX_LENGTH) { + || username.length() > UserConstants.USERNAME_MAX_LENGTH) { throw new ServiceException("账户长度必须在2到20个字符之间"); } if (password.length() < UserConstants.PASSWORD_MIN_LENGTH - || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { throw new ServiceException("密码长度必须在5到20个字符之间"); } diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index 2b03d5289..2c190edda 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -17,6 +17,7 @@ ruoyi-common-redis ruoyi-common-swagger ruoyi-common-security + ruoyi-common-satoken ruoyi-common-datasource ruoyi-common-web ruoyi-common-mybatis diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml index d0523a8f0..24421a09d 100644 --- a/ruoyi-common/ruoyi-common-bom/pom.xml +++ b/ruoyi-common/ruoyi-common-bom/pom.xml @@ -36,6 +36,12 @@ ${project.version} + + com.ruoyi + ruoyi-common-satoken + ${project.version} + + com.ruoyi diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml index 7e4846893..977f4d89c 100644 --- a/ruoyi-common/ruoyi-common-core/pom.xml +++ b/ruoyi-common/ruoyi-common-core/pom.xml @@ -29,12 +29,6 @@ spring-web - - - com.alibaba - transmittable-thread-local - - org.mybatis.spring.boot mybatis-spring-boot-starter @@ -111,11 +105,6 @@ hutool-core - - cn.hutool - hutool-jwt - - cn.hutool hutool-http diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java index 1fa041fd9..15414a308 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java @@ -1,23 +1,40 @@ -package com.ruoyi.common.core.constant; - -/** - * 缓存的key 常量 - * - * @author Lion Li - */ -public interface CacheConstants { - /** - * 缓存有效期,默认720(分钟) - */ - long EXPIRATION = 720; - - /** - * 缓存刷新时间,默认120(分钟) - */ - long REFRESH_TIME = 120; - - /** - * 权限缓存前缀 - */ - String LOGIN_TOKEN_KEY = "login_tokens:"; -} +package com.ruoyi.common.core.constant; + +/** + * 缓存的key 常量 + * + * @author Lion Li + */ +public interface CacheConstants { + + /** + * 登录用户 redis key + */ + String LOGIN_TOKEN_KEY = "Authorization:login:token:"; + + /** + * 在线用户 redis key + */ + String ONLINE_TOKEN_KEY = "online_tokens:"; + + /** + * loginid构造拼接字符串 + */ + String LOGINID_JOIN_CODE = ":"; + + /** + * 登陆错误 redis key + */ + String LOGIN_ERROR = "login_error:"; + + /** + * 登录错误次数 + */ + Integer LOGIN_ERROR_NUMBER = 5; + + /** + * 登录错误限制时间(分钟) + */ + Integer LOGIN_ERROR_LIMIT_TIME = 10; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/context/SecurityContextHolder.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/context/SecurityContextHolder.java deleted file mode 100644 index e6761d645..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/context/SecurityContextHolder.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.ruoyi.common.core.context; - -import cn.hutool.core.convert.Convert; -import com.alibaba.ttl.TransmittableThreadLocal; -import com.ruoyi.common.core.constant.SecurityConstants; -import com.ruoyi.common.core.utils.StringUtils; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 获取当前线程变量中的 用户id、用户名称、Token等信息 - * 注意: 必须在网关通过请求头的方法传入,同时在HeaderInterceptor拦截器设置值。 否则这里无法获取 - * - * @author ruoyi - */ -public class SecurityContextHolder { - private static final TransmittableThreadLocal> THREAD_LOCAL = new TransmittableThreadLocal<>(); - - public static void set(String key, Object value) { - Map map = getLocalMap(); - map.put(key, value == null ? StringUtils.EMPTY : value); - } - - public static String get(String key) { - Map map = getLocalMap(); - return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY)); - } - - public static T get(String key, Class clazz) { - Map map = getLocalMap(); - return StringUtils.cast(map.getOrDefault(key, null)); - } - - public static Map getLocalMap() { - Map map = THREAD_LOCAL.get(); - if (map == null) { - map = new ConcurrentHashMap(); - THREAD_LOCAL.set(map); - } - return map; - } - - public static void setLocalMap(Map threadLocalMap) { - THREAD_LOCAL.set(threadLocalMap); - } - - public static Long getUserId() { - return Convert.toLong(get(SecurityConstants.DETAILS_USER_ID), 0L); - } - - public static void setUserId(String account) { - set(SecurityConstants.DETAILS_USER_ID, account); - } - - public static String getUserName() { - return get(SecurityConstants.DETAILS_USERNAME); - } - - public static void setUserName(String username) { - set(SecurityConstants.DETAILS_USERNAME, username); - } - - public static String getUserKey() { - return get(SecurityConstants.USER_KEY); - } - - public static void setUserKey(String userKey) { - set(SecurityConstants.USER_KEY, userKey); - } - - public static void remove() { - THREAD_LOCAL.remove(); - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java new file mode 100644 index 000000000..981b2cc92 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java @@ -0,0 +1,27 @@ +package com.ruoyi.common.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 设备类型 + * 针对一套 用户体系 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum DeviceType { + + /** + * pc端 + */ + PC("pc"), + + /** + * app端 + */ + APP("app"); + + private final String device; +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java new file mode 100644 index 000000000..46e400587 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java @@ -0,0 +1,37 @@ +package com.ruoyi.common.core.enums; + +import com.ruoyi.common.core.utils.StringUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 设备类型 + * 针对多套 用户体系 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum UserType { + + /** + * pc端 + */ + SYS_USER("sys_user"), + + /** + * app端 + */ + APP_USER("app_user"); + + private final String userType; + + public static UserType getUserType(String str) { + for (UserType value : values()) { + if (StringUtils.contains(str, value.getUserType())) { + return value; + } + } + throw new RuntimeException("'UserType' not found By " + str); + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java deleted file mode 100644 index 5cc2eadc7..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ruoyi.common.core.exception; - -/** - * 内部认证异常 - * - * @author ruoyi - */ -public class InnerAuthException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public InnerAuthException(String message) { - super(message); - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/PreAuthorizeException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/PreAuthorizeException.java deleted file mode 100644 index 5d786c3ab..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/PreAuthorizeException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ruoyi.common.core.exception; - -/** - * 权限异常 - * - * @author ruoyi - */ -public class PreAuthorizeException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public PreAuthorizeException() { - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotLoginException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotLoginException.java deleted file mode 100644 index 47ce5aba2..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotLoginException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ruoyi.common.core.exception.auth; - -/** - * 未能通过的登录认证异常 - * - * @author ruoyi - */ -public class NotLoginException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public NotLoginException(String message) { - super(message); - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotPermissionException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotPermissionException.java deleted file mode 100644 index 82994f021..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotPermissionException.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ruoyi.common.core.exception.auth; - -import org.apache.commons.lang3.StringUtils; - -/** - * 未能通过的权限认证异常 - * - * @author ruoyi - */ -public class NotPermissionException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public NotPermissionException(String permission) { - super(permission); - } - - public NotPermissionException(String[] permissions) { - super(StringUtils.join(permissions, ",")); - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotRoleException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotRoleException.java deleted file mode 100644 index 84abe1375..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotRoleException.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ruoyi.common.core.exception.auth; - -import org.apache.commons.lang3.StringUtils; - -/** - * 未能通过的角色认证异常 - * - * @author ruoyi - */ -public class NotRoleException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public NotRoleException(String role) { - super(role); - } - - public NotRoleException(String[] roles) { - super(StringUtils.join(roles, ",")); - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java index c7b8aefd8..a65c05642 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java @@ -1,16 +1,16 @@ -package com.ruoyi.common.core.exception.user; - -import com.ruoyi.common.core.exception.base.BaseException; - -/** - * 用户信息异常类 - * - * @author ruoyi - */ -public class UserException extends BaseException { - private static final long serialVersionUID = 1L; - - public UserException(String code, Object[] args) { - super("user", code, args, null); - } -} +package com.ruoyi.common.core.exception.user; + +import com.ruoyi.common.core.exception.base.BaseException; + +/** + * 用户信息异常类 + * + * @author ruoyi + */ +public class UserException extends BaseException { + private static final long serialVersionUID = 1L; + + public UserException(String code, Object[] args) { + super("user", code, args, null); + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/JwtUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/JwtUtils.java deleted file mode 100644 index 84a049f63..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/JwtUtils.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.ruoyi.common.core.utils; - -import cn.hutool.core.convert.Convert; -import cn.hutool.json.JSONObject; -import cn.hutool.jwt.JWTUtil; -import cn.hutool.jwt.signers.JWTSigner; -import cn.hutool.jwt.signers.JWTSignerUtil; -import com.ruoyi.common.core.constant.SecurityConstants; -import com.ruoyi.common.core.constant.TokenConstants; - -import java.util.Map; - -/** - * Jwt工具类 - * - * @author ruoyi - */ -public class JwtUtils { - public static String secret = TokenConstants.SECRET; - - /** - * 从数据声明生成令牌 - * - * @param claims 数据声明 - * @return 令牌 - */ - public static String createToken(Map claims) { - JWTSigner signer = JWTSignerUtil.hs512(secret.getBytes()); - String token = JWTUtil.createToken(claims, signer); - return token; - } - - /** - * 从令牌中获取数据声明 - * - * @param token 令牌 - * @return 数据声明 - */ - public static JSONObject parseToken(String token) { - JWTSigner signer = JWTSignerUtil.hs512(secret.getBytes()); - return JWTUtil.parseToken(token).setSigner(signer).getPayload().getClaimsJson(); - } - - /** - * 根据令牌获取用户标识 - * - * @param token 令牌 - * @return 用户ID - */ - public static String getUserKey(String token) { - JSONObject claims = parseToken(token); - return getValue(claims, SecurityConstants.USER_KEY); - } - - /** - * 根据令牌获取用户标识 - * - * @param claims 身份信息 - * @return 用户ID - */ - public static String getUserKey(JSONObject claims) { - return getValue(claims, SecurityConstants.USER_KEY); - } - - /** - * 根据令牌获取用户ID - * - * @param token 令牌 - * @return 用户ID - */ - public static String getUserId(String token) { - JSONObject claims = parseToken(token); - return getValue(claims, SecurityConstants.DETAILS_USER_ID); - } - - /** - * 根据身份信息获取用户ID - * - * @param claims 身份信息 - * @return 用户ID - */ - public static String getUserId(JSONObject claims) { - return getValue(claims, SecurityConstants.DETAILS_USER_ID); - } - - /** - * 根据令牌获取用户名 - * - * @param token 令牌 - * @return 用户名 - */ - public static String getUserName(String token) { - JSONObject claims = parseToken(token); - return getValue(claims, SecurityConstants.DETAILS_USERNAME); - } - - /** - * 根据身份信息获取用户名 - * - * @param claims 身份信息 - * @return 用户名 - */ - public static String getUserName(JSONObject claims) { - return getValue(claims, SecurityConstants.DETAILS_USERNAME); - } - - /** - * 根据身份信息获取键值 - * - * @param claims 身份信息 - * @param key 键 - * @return 值 - */ - public static String getValue(JSONObject claims, String key) { - return Convert.toStr(claims.get(key), ""); - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java new file mode 100644 index 000000000..8bf6ffdff --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java @@ -0,0 +1,60 @@ +package com.ruoyi.common.core.utils.ip; + +import cn.hutool.core.net.NetUtil; +import cn.hutool.http.HtmlUtil; +import cn.hutool.http.HttpUtil; +import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.utils.JsonUtils; +import com.ruoyi.common.core.utils.StringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +/** + * 获取地址类 + * + * @author Lion Li + */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class AddressUtils { + + // IP地址查询 + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; + + // 未知地址 + public static final String UNKNOWN = "XX XX"; + + public static String getRealAddressByIP(String ip) { + String address = UNKNOWN; + if (StringUtils.isBlank(ip)) { + return address; + } + // 内网不查询 + ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip); + if (NetUtil.isInnerIP(ip)) { + return "内网IP"; + } +// if (RuoYiConfig.isAddressEnabled()) { + try { + String rspStr = HttpUtil.createGet(IP_URL) + .body("ip=" + ip + "&json=true", Constants.GBK) + .execute() + .body(); + if (StringUtils.isEmpty(rspStr)) { + log.error("获取地理位置异常 {}", ip); + return UNKNOWN; + } + Map obj = JsonUtils.parseMap(rspStr); + String region = obj.get("pro"); + String city = obj.get("city"); + return String.format("%s %s", region, city); + } catch (Exception e) { + log.error("获取地理位置异常 {}", ip); + } +// } + return address; + } +} diff --git a/ruoyi-common/ruoyi-common-dubbo/pom.xml b/ruoyi-common/ruoyi-common-dubbo/pom.xml index 3b6a46b2b..507c45c45 100644 --- a/ruoyi-common/ruoyi-common-dubbo/pom.xml +++ b/ruoyi-common/ruoyi-common-dubbo/pom.xml @@ -47,5 +47,18 @@ org.projectlombok lombok + + + + cn.dev33 + sa-token-context-dubbo + ${satoken.version} + + + org.apache.dubbo + dubbo + + + diff --git a/ruoyi-common/ruoyi-common-dubbo/src/main/java/com/ruoyi/common/dubbo/filter/DubboRequestFilter.java b/ruoyi-common/ruoyi-common-dubbo/src/main/java/com/ruoyi/common/dubbo/filter/DubboRequestFilter.java index 65fab633d..42b1d0e07 100644 --- a/ruoyi-common/ruoyi-common-dubbo/src/main/java/com/ruoyi/common/dubbo/filter/DubboRequestFilter.java +++ b/ruoyi-common/ruoyi-common-dubbo/src/main/java/com/ruoyi/common/dubbo/filter/DubboRequestFilter.java @@ -16,7 +16,7 @@ import org.apache.dubbo.rpc.service.GenericService; * @author Lion Li */ @Slf4j -@Activate(group = { CommonConstants.PROVIDER, CommonConstants.CONSUMER }) +@Activate(group = {CommonConstants.PROVIDER, CommonConstants.CONSUMER}) public class DubboRequestFilter implements Filter { @Override diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java index 43f7409f7..de6ca0145 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java @@ -7,7 +7,7 @@ import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessStatus; import com.ruoyi.common.log.service.AsyncLogService; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.domain.SysOperLog; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; @@ -67,7 +67,7 @@ public class LogAspect { // 请求的地址 operLog.setOperIp(ServletUtils.getClientIP()); operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); - String username = SecurityUtils.getUsername(); + String username = LoginHelper.getUsername(); if (StringUtils.isNotBlank(username)) { operLog.setOperName(username); } diff --git a/ruoyi-common/ruoyi-common-mybatis/pom.xml b/ruoyi-common/ruoyi-common-mybatis/pom.xml index 4ef78316c..7a7e342a0 100644 --- a/ruoyi-common/ruoyi-common-mybatis/pom.xml +++ b/ruoyi-common/ruoyi-common-mybatis/pom.xml @@ -22,6 +22,12 @@ provided + + com.ruoyi + ruoyi-common-dubbo + provided + + com.baomidou mybatis-plus-boot-starter diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java index 3d5a3190e..65ac42f05 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java @@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.web.domain.BaseEntity; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.model.LoginUser; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; @@ -68,7 +68,7 @@ public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler { private String getLoginUsername() { LoginUser loginUser; try { - loginUser = SecurityUtils.getLoginUser(); + loginUser = LoginHelper.getLoginUser(); } catch (Exception e) { log.warn("自动注入警告 => 用户未登录"); return null; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java index bf692c3ec..fe64e6198 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java @@ -12,9 +12,10 @@ import com.ruoyi.common.mybatis.annotation.DataColumn; import com.ruoyi.common.mybatis.annotation.DataPermission; import com.ruoyi.common.mybatis.enums.DataScopeType; import com.ruoyi.common.mybatis.helper.DataPermissionHelper; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.common.security.utils.SecurityUtils; -import com.ruoyi.system.api.domain.SysRole; -import com.ruoyi.system.api.domain.SysUser; +import com.ruoyi.system.api.model.LoginUser; +import com.ruoyi.system.api.model.RoleDTO; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; @@ -73,13 +74,13 @@ public class PlusDataPermissionHandler { inavlidCacheSet.add(mappedStatementId); return where; } - SysUser currentUser = DataPermissionHelper.getVariable("user"); + LoginUser currentUser = DataPermissionHelper.getVariable("user"); if (ObjectUtil.isNull(currentUser)) { - currentUser = SecurityUtils.getLoginUser().getSysUser(); + currentUser = LoginHelper.getLoginUser(); DataPermissionHelper.setVariable("user", currentUser); } // 如果是超级管理员,则不过滤数据 - if (ObjectUtil.isNull(currentUser) || currentUser.isAdmin()) { + if (ObjectUtil.isNull(currentUser) || SecurityUtils.isAdmin(currentUser.getUserId())) { return where; } String dataFilterSql = buildDataFilter(dataColumns, isSelect); @@ -107,12 +108,12 @@ public class PlusDataPermissionHandler { StringBuilder sqlString = new StringBuilder(); // 更新或删除需满足所有条件 String joinStr = isSelect ? " OR " : " AND "; - SysUser user = DataPermissionHelper.getVariable("user"); + LoginUser loginUser = DataPermissionHelper.getVariable("user"); StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(beanResolver); DataPermissionHelper.getContext().forEach(context::setVariable); - for (SysRole role : user.getRoles()) { - user.setRoleId(role.getRoleId()); + for (RoleDTO role : loginUser.getRoles()) { + loginUser.setRoleId(role.getRoleId()); // 获取角色权限泛型 DataScopeType type = DataScopeType.findCode(role.getDataScope()); if (ObjectUtil.isNull(type)) { diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/service/SysDataScopeService.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/service/SysDataScopeService.java new file mode 100644 index 000000000..793175a1f --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/service/SysDataScopeService.java @@ -0,0 +1,25 @@ +package com.ruoyi.common.mybatis.service; + +import com.ruoyi.system.api.RemoteDataScopeService; +import org.apache.dubbo.config.annotation.DubboReference; +import org.springframework.stereotype.Service; + +/** + * 数据权限服务 + * + * @author Lion Li + */ +@Service("sdss") +public class SysDataScopeService { + + @DubboReference + private RemoteDataScopeService remoteDataScopeService; + + public String getRoleCustom(Long roleId) { + return remoteDataScopeService.getRoleCustom(roleId); + } + + public String getDeptAndChild(Long deptId) { + return remoteDataScopeService.getDeptAndChild(deptId); + } +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring.factories b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring.factories index 328645864..6df5c2ecc 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring.factories +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.ruoyi.common.mybatis.config.MybatisPlusConfiguration + com.ruoyi.common.mybatis.config.MybatisPlusConfiguration,\ + com.ruoyi.common.mybatis.service.SysDataScopeService diff --git a/ruoyi-common/ruoyi-common-satoken/pom.xml b/ruoyi-common/ruoyi-common-satoken/pom.xml new file mode 100644 index 000000000..7cec07196 --- /dev/null +++ b/ruoyi-common/ruoyi-common-satoken/pom.xml @@ -0,0 +1,47 @@ + + + + com.ruoyi + ruoyi-common + 0.4.0 + + 4.0.0 + + ruoyi-common-satoken + + + ruoyi-common-satoken + + + + + + + cn.dev33 + sa-token-core + ${satoken.version} + + + + + cn.dev33 + sa-token-jwt + ${satoken.version} + + + + + com.ruoyi + ruoyi-api-system + + + + + com.ruoyi + ruoyi-common-redis + + + + + diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/config/SaTokenConfiguration.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/config/SaTokenConfiguration.java new file mode 100644 index 000000000..c33c7cc23 --- /dev/null +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/config/SaTokenConfiguration.java @@ -0,0 +1,21 @@ +package com.ruoyi.common.satoken.config; + +import cn.dev33.satoken.jwt.StpLogicJwtForStyle; +import cn.dev33.satoken.stp.StpLogic; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Sa-Token 配置 + * + * @author Lion Li + */ +@Configuration +public class SaTokenConfiguration { + + @Bean + public StpLogic getStpLogicJwt() { + return new StpLogicJwtForStyle(); + } + +} diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/dao/PlusSaTokenDao.java new file mode 100644 index 000000000..3ae72ef1c --- /dev/null +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/dao/PlusSaTokenDao.java @@ -0,0 +1,177 @@ +package com.ruoyi.common.satoken.core.dao; + +import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.util.SaFoxUtil; +import com.ruoyi.common.redis.utils.RedisUtils; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * Sa-Token持久层接口(使用框架自带RedisUtils实现 协议统一) + * + * @author Lion Li + */ +@Component +public class PlusSaTokenDao implements SaTokenDao { + + /** + * 获取Value,如无返空 + */ + @Override + public String get(String key) { + return RedisUtils.getCacheObject(key); + } + + /** + * 写入Value,并设定存活时间 (单位: 秒) + */ + @Override + public void set(String key, String value, long timeout) { + if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + // 判断是否为永不过期 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + RedisUtils.setCacheObject(key, value); + } else { + RedisUtils.setCacheObject(key, value, timeout, TimeUnit.SECONDS); + } + } + + /** + * 修修改指定key-value键值对 (过期时间不变) + */ + @Override + public void update(String key, String value) { + long expire = getTimeout(key); + // -2 = 无此键 + if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + this.set(key, value, expire); + } + + /** + * 删除Value + */ + @Override + public void delete(String key) { + RedisUtils.deleteObject(key); + } + + /** + * 获取Value的剩余存活时间 (单位: 秒) + */ + @Override + public long getTimeout(String key) { + return RedisUtils.getTimeToLive(key) / 1000; + } + + /** + * 修改Value的剩余存活时间 (单位: 秒) + */ + @Override + public void updateTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + long expire = getTimeout(key); + if (expire == SaTokenDao.NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.set(key, this.get(key), timeout); + } + return; + } + RedisUtils.expire(key, timeout, TimeUnit.SECONDS); + } + + + /** + * 获取Object,如无返空 + */ + @Override + public Object getObject(String key) { + return RedisUtils.getCacheObject(key); + } + + /** + * 写入Object,并设定存活时间 (单位: 秒) + */ + @Override + public void setObject(String key, Object object, long timeout) { + if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + // 判断是否为永不过期 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + RedisUtils.setCacheObject(key, object); + } else { + RedisUtils.setCacheObject(key, object, timeout, TimeUnit.SECONDS); + } + } + + /** + * 更新Object (过期时间不变) + */ + @Override + public void updateObject(String key, Object object) { + long expire = getObjectTimeout(key); + // -2 = 无此键 + if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + this.setObject(key, object, expire); + } + + /** + * 删除Object + */ + @Override + public void deleteObject(String key) { + RedisUtils.deleteObject(key); + } + + /** + * 获取Object的剩余存活时间 (单位: 秒) + */ + @Override + public long getObjectTimeout(String key) { + return RedisUtils.getTimeToLive(key) / 1000; + } + + /** + * 修改Object的剩余存活时间 (单位: 秒) + */ + @Override + public void updateObjectTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + long expire = getObjectTimeout(key); + if (expire == SaTokenDao.NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.setObject(key, this.getObject(key), timeout); + } + return; + } + RedisUtils.expire(key, timeout, TimeUnit.SECONDS); + } + + + /** + * 搜索数据 + */ + @Override + public List searchData(String prefix, String keyword, int start, int size) { + Collection keys = RedisUtils.keys(prefix + "*" + keyword + "*"); + List list = new ArrayList<>(keys); + return SaFoxUtil.searchList(list, start, size); + } + +} diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/service/SaInterfaceImpl.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/service/SaInterfaceImpl.java new file mode 100644 index 000000000..5eda215b4 --- /dev/null +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/service/SaInterfaceImpl.java @@ -0,0 +1,43 @@ +package com.ruoyi.common.satoken.core.service; + +import cn.dev33.satoken.stp.StpInterface; +import com.ruoyi.common.core.enums.UserType; +import com.ruoyi.common.satoken.utils.LoginHelper; +import com.ruoyi.system.api.model.LoginUser; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * 权限认证接口实现 + * + * @author Lion Li + */ +@Component +public class SaInterfaceImpl implements StpInterface { + + @Override + public List getPermissionList(Object loginId, String loginType) { + LoginUser loginUser = LoginHelper.getLoginUser(); + UserType userType = UserType.getUserType(loginUser.getUserType()); + if (userType == UserType.SYS_USER) { + return new ArrayList<>(loginUser.getMenuPermission()); + } else if (userType == UserType.APP_USER) { + // app端权限返回 自行根据业务编写 + } + return new ArrayList<>(); + } + + @Override + public List getRoleList(Object loginId, String loginType) { + LoginUser loginUser = LoginHelper.getLoginUser(); + UserType userType = UserType.getUserType(loginUser.getUserType()); + if (userType == UserType.SYS_USER) { + return new ArrayList<>(loginUser.getRolePermission()); + } else if (userType == UserType.APP_USER) { + // app端权限返回 自行根据业务编写 + } + return new ArrayList<>(); + } +} diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/utils/LoginHelper.java new file mode 100644 index 000000000..422c74a09 --- /dev/null +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/utils/LoginHelper.java @@ -0,0 +1,121 @@ +package com.ruoyi.common.satoken.utils; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.ObjectUtil; +import com.ruoyi.common.core.enums.DeviceType; +import com.ruoyi.common.core.enums.UserType; +import com.ruoyi.common.core.exception.UtilException; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.system.api.model.LoginUser; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** + * 登录鉴权助手 + * 为适配多端登录而封装 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class LoginHelper { + + public static final String JOIN_CODE = ":"; + public static final String LOGIN_USER_KEY = "loginUser"; + + private static final ThreadLocal LOGIN_CACHE = new ThreadLocal<>(); + + /** + * 登录系统 + * 针对两套用户体系 + * + * @param loginUser 登录用户信息 + */ + public static void login(LoginUser loginUser) { + LOGIN_CACHE.set(loginUser); + StpUtil.login(loginUser.getLoginId()); + setLoginUser(loginUser); + } + + /** + * 登录系统 基于 设备类型 + * 针对一套用户体系 + * + * @param loginUser 登录用户信息 + */ + public static void loginByDevice(LoginUser loginUser, DeviceType deviceType) { + LOGIN_CACHE.set(loginUser); + StpUtil.login(loginUser.getLoginId(), deviceType.getDevice()); + setLoginUser(loginUser); + } + + /** + * 设置用户数据(多级缓存) + */ + public static void setLoginUser(LoginUser loginUser) { + StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser); + } + + /** + * 获取用户(多级缓存) + */ + public static LoginUser getLoginUser() { + LoginUser loginUser = LOGIN_CACHE.get(); + if (loginUser != null) { + return loginUser; + } + return (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY); + } + + /** + * 清除一级缓存 防止内存问题 + */ + public static void clearCache() { + LOGIN_CACHE.remove(); + } + + /** + * 获取用户id + */ + public static Long getUserId() { + LoginUser loginUser = getLoginUser(); + if (ObjectUtil.isNull(loginUser)) { + String loginId = StpUtil.getLoginIdAsString(); + String userId = null; + for (UserType value : UserType.values()) { + if (StringUtils.contains(loginId, value.getUserType())) { + String[] strs = StringUtils.split(loginId, JOIN_CODE); + // 用户id在总是在最后 + userId = strs[strs.length - 1]; + } + } + if (StringUtils.isBlank(userId)) { + throw new UtilException("登录用户: LoginId异常 => " + loginId); + } + return Long.parseLong(userId); + } + return loginUser.getUserId(); + } + + /** + * 获取部门ID + */ + public static Long getDeptId() { + return getLoginUser().getDeptId(); + } + + /** + * 获取用户账户 + */ + public static String getUsername() { + return getLoginUser().getUsername(); + } + + /** + * 获取用户类型 + */ + public static UserType getUserType() { + String loginId = StpUtil.getLoginIdAsString(); + return UserType.getUserType(loginId); + } + +} diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring.factories b/ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..870b28504 --- /dev/null +++ b/ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring.factories @@ -0,0 +1,4 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.ruoyi.common.satoken.core.dao.PlusSaTokenDao,\ + com.ruoyi.common.satoken.core.service.SaInterfaceImpl,\ + com.ruoyi.common.satoken.config.SaTokenConfiguration diff --git a/ruoyi-common/ruoyi-common-security/pom.xml b/ruoyi-common/ruoyi-common-security/pom.xml index 2bd4c61fc..77b677aba 100644 --- a/ruoyi-common/ruoyi-common-security/pom.xml +++ b/ruoyi-common/ruoyi-common-security/pom.xml @@ -16,31 +16,18 @@ - - - org.springframework - spring-webmvc - - - com.ruoyi - ruoyi-api-system - ${project.version} + ruoyi-common-satoken - + - com.ruoyi - ruoyi-common-redis + cn.dev33 + sa-token-spring-boot-starter + ${satoken.version} - - - - - - diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java index 7aeb4569c..21ba351ba 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java @@ -11,8 +11,6 @@ import java.lang.annotation.*; @Inherited // 表示通过aop框架暴露该代理对象,AopContext能够访问 @EnableAspectJAutoProxy(exposeProxy = true) -//// 指定要扫描的Mapper类的包的路径 -//@MapperScan("com.ruoyi.**.mapper") // 开启线程异步执行 @EnableAsync public @interface EnableCustomConfig { diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/InnerAuth.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/InnerAuth.java deleted file mode 100644 index a6f26d800..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/InnerAuth.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi.common.security.annotation; - -import java.lang.annotation.*; - -/** - * 内部认证注解 - * - * @author ruoyi - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface InnerAuth { - /** - * 是否校验用户信息 - */ - boolean isUser() default false; -} \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/Logical.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/Logical.java deleted file mode 100644 index 1d633674e..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/Logical.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi.common.security.annotation; - -/** - * 权限注解的验证模式 - * - * @author ruoyi - */ -public enum Logical { - /** - * 必须具有所有的元素 - */ - AND, - - /** - * 只需具有其中一个元素 - */ - OR -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresLogin.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresLogin.java deleted file mode 100644 index e7cf713f5..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresLogin.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.common.security.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 登录认证:只有登录之后才能进入该方法 - * - * @author ruoyi - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface RequiresLogin { -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresPermissions.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresPermissions.java deleted file mode 100644 index 5ff5ed3e6..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresPermissions.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ruoyi.common.security.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 权限认证:必须具有指定权限才能进入该方法 - * - * @author ruoyi - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface RequiresPermissions { - /** - * 需要校验的权限码 - */ - String[] value() default {}; - - /** - * 验证模式:AND | OR,默认AND - */ - Logical logical() default Logical.AND; -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresRoles.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresRoles.java deleted file mode 100644 index d703069a4..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/RequiresRoles.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ruoyi.common.security.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 角色认证:必须具有指定角色标识才能进入该方法 - * - * @author ruoyi - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface RequiresRoles { - /** - * 需要校验的角色标识 - */ - String[] value() default {}; - - /** - * 验证逻辑:AND | OR,默认AND - */ - Logical logical() default Logical.AND; -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/InnerAuthAspect.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/InnerAuthAspect.java deleted file mode 100644 index 58e5beda5..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/InnerAuthAspect.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.ruoyi.common.security.aspect; - -import com.ruoyi.common.core.constant.SecurityConstants; -import com.ruoyi.common.core.exception.InnerAuthException; -import com.ruoyi.common.core.utils.ServletUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.security.annotation.InnerAuth; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; - -/** - * 内部服务调用验证处理 - * - * @author ruoyi - */ -@Aspect -@Component -public class InnerAuthAspect implements Ordered { - @Around("@annotation(innerAuth)") - public Object innerAround(ProceedingJoinPoint point, InnerAuth innerAuth) throws Throwable { - String source = ServletUtils.getRequest().getHeader(SecurityConstants.FROM_SOURCE); - // 内部请求验证 - if (!StringUtils.equals(SecurityConstants.INNER, source)) { - throw new InnerAuthException("没有内部访问权限,不允许访问"); - } - - String userid = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USER_ID); - String username = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USERNAME); - // 用户信息验证 - if (innerAuth.isUser() && (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username))) { - throw new InnerAuthException("没有设置用户信息,不允许访问 "); - } - return point.proceed(); - } - - /** - * 确保在权限认证aop执行前执行 - */ - @Override - public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE + 1; - } -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/PreAuthorizeAspect.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/PreAuthorizeAspect.java deleted file mode 100644 index 81134ee5a..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/PreAuthorizeAspect.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.ruoyi.common.security.aspect; - -import com.ruoyi.common.security.annotation.RequiresLogin; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.annotation.RequiresRoles; -import com.ruoyi.common.security.auth.AuthUtil; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; - -import java.lang.reflect.Method; - -/** - * 基于 Spring Aop 的注解鉴权 - * - * @author kong - */ -@Aspect -@Component -public class PreAuthorizeAspect { - /** - * 构建 - */ - public PreAuthorizeAspect() { - } - - /** - * 定义AOP签名 (切入所有使用鉴权注解的方法) - */ - public static final String POINTCUT_SIGN = " @annotation(com.ruoyi.common.security.annotation.RequiresLogin) || " - + "@annotation(com.ruoyi.common.security.annotation.RequiresPermissions) || " - + "@annotation(com.ruoyi.common.security.annotation.RequiresRoles)"; - - /** - * 声明AOP签名 - */ - @Pointcut(POINTCUT_SIGN) - public void pointcut() { - } - - /** - * 环绕切入 - * - * @param joinPoint 切面对象 - * @return 底层方法执行后的返回值 - * @throws Throwable 底层方法抛出的异常 - */ - @Around("pointcut()") - public Object around(ProceedingJoinPoint joinPoint) throws Throwable { - // 注解鉴权 - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - checkMethodAnnotation(signature.getMethod()); - try { - // 执行原有逻辑 - Object obj = joinPoint.proceed(); - return obj; - } catch (Throwable e) { - throw e; - } - } - - /** - * 对一个Method对象进行注解检查 - */ - public void checkMethodAnnotation(Method method) { - // 校验 @RequiresLogin 注解 - RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class); - if (requiresLogin != null) { - AuthUtil.checkLogin(); - } - - // 校验 @RequiresRoles 注解 - RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class); - if (requiresRoles != null) { - AuthUtil.checkRole(requiresRoles); - } - - // 校验 @RequiresPermissions 注解 - RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class); - if (requiresPermissions != null) { - AuthUtil.checkPermi(requiresPermissions); - } - } -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/auth/AuthLogic.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/auth/AuthLogic.java deleted file mode 100644 index 70ecd2b55..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/auth/AuthLogic.java +++ /dev/null @@ -1,319 +0,0 @@ -package com.ruoyi.common.security.auth; - -import com.ruoyi.common.core.exception.auth.NotLoginException; -import com.ruoyi.common.core.exception.auth.NotPermissionException; -import com.ruoyi.common.core.exception.auth.NotRoleException; -import com.ruoyi.common.core.utils.SpringUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.security.annotation.Logical; -import com.ruoyi.common.security.annotation.RequiresLogin; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.annotation.RequiresRoles; -import com.ruoyi.common.security.service.TokenService; -import com.ruoyi.common.security.utils.SecurityUtils; -import com.ruoyi.system.api.model.LoginUser; -import org.springframework.util.PatternMatchUtils; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * Token 权限验证,逻辑实现类 - * - * @author ruoyi - */ -public class AuthLogic { - /** - * 所有权限标识 - */ - private static final String ALL_PERMISSION = "*:*:*"; - - /** - * 管理员角色权限标识 - */ - private static final String SUPER_ADMIN = "admin"; - - public TokenService tokenService = SpringUtils.getBean(TokenService.class); - - /** - * 会话注销 - */ - public void logout() { - String token = SecurityUtils.getToken(); - if (token == null) { - return; - } - logoutByToken(token); - } - - /** - * 会话注销,根据指定Token - */ - public void logoutByToken(String token) { - tokenService.delLoginUser(token); - } - - /** - * 检验用户是否已经登录,如未登录,则抛出异常 - */ - public void checkLogin() { - getLoginUser(); - } - - /** - * 获取当前用户缓存信息, 如果未登录,则抛出异常 - * - * @return 用户缓存信息 - */ - public LoginUser getLoginUser() { - String token = SecurityUtils.getToken(); - if (token == null) { - throw new NotLoginException("未提供token"); - } - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (loginUser == null) { - throw new NotLoginException("无效的token"); - } - return loginUser; - } - - /** - * 获取当前用户缓存信息, 如果未登录,则抛出异常 - * - * @param token 前端传递的认证信息 - * @return 用户缓存信息 - */ - public LoginUser getLoginUser(String token) { - return tokenService.getLoginUser(token); - } - - /** - * 验证当前用户有效期, 如果相差不足360分钟,自动刷新缓存 - * - * @param loginUser 当前用户信息 - */ - public void verifyLoginUserExpire(LoginUser loginUser) { - tokenService.verifyToken(loginUser); - } - - /** - * 验证用户是否具备某权限 - * - * @param permission 权限字符串 - * @return 用户是否具备某权限 - */ - public boolean hasPermi(String permission) { - return hasPermi(getPermiList(), permission); - } - - /** - * 验证用户是否具备某权限, 如果验证未通过,则抛出异常: NotPermissionException - * - * @param permission 权限字符串 - * @return 用户是否具备某权限 - */ - public void checkPermi(String permission) { - if (!hasPermi(getPermiList(), permission)) { - throw new NotPermissionException(permission); - } - } - - /** - * 根据注解(@RequiresPermissions)鉴权, 如果验证未通过,则抛出异常: NotPermissionException - * - * @param requiresPermissions 注解对象 - */ - public void checkPermi(RequiresPermissions requiresPermissions) { - if (requiresPermissions.logical() == Logical.AND) { - checkPermiAnd(requiresPermissions.value()); - } else { - checkPermiOr(requiresPermissions.value()); - } - } - - /** - * 验证用户是否含有指定权限,必须全部拥有 - * - * @param permissions 权限列表 - */ - public void checkPermiAnd(String... permissions) { - Set permissionList = getPermiList(); - for (String permission : permissions) { - if (!hasPermi(permissionList, permission)) { - throw new NotPermissionException(permission); - } - } - } - - /** - * 验证用户是否含有指定权限,只需包含其中一个 - * - * @param permissions 权限码数组 - */ - public void checkPermiOr(String... permissions) { - Set permissionList = getPermiList(); - for (String permission : permissions) { - if (hasPermi(permissionList, permission)) { - return; - } - } - if (permissions.length > 0) { - throw new NotPermissionException(permissions); - } - } - - /** - * 判断用户是否拥有某个角色 - * - * @param role 角色标识 - * @return 用户是否具备某角色 - */ - public boolean hasRole(String role) { - return hasRole(getRoleList(), role); - } - - /** - * 判断用户是否拥有某个角色, 如果验证未通过,则抛出异常: NotRoleException - * - * @param role 角色标识 - */ - public void checkRole(String role) { - if (!hasRole(role)) { - throw new NotRoleException(role); - } - } - - /** - * 根据注解(@RequiresRoles)鉴权 - * - * @param requiresRoles 注解对象 - */ - public void checkRole(RequiresRoles requiresRoles) { - if (requiresRoles.logical() == Logical.AND) { - checkRoleAnd(requiresRoles.value()); - } else { - checkRoleOr(requiresRoles.value()); - } - } - - /** - * 验证用户是否含有指定角色,必须全部拥有 - * - * @param roles 角色标识数组 - */ - public void checkRoleAnd(String... roles) { - Set roleList = getRoleList(); - for (String role : roles) { - if (!hasRole(roleList, role)) { - throw new NotRoleException(role); - } - } - } - - /** - * 验证用户是否含有指定角色,只需包含其中一个 - * - * @param roles 角色标识数组 - */ - public void checkRoleOr(String... roles) { - Set roleList = getRoleList(); - for (String role : roles) { - if (hasRole(roleList, role)) { - return; - } - } - if (roles.length > 0) { - throw new NotRoleException(roles); - } - } - - /** - * 根据注解(@RequiresLogin)鉴权 - * - * @param at 注解对象 - */ - public void checkByAnnotation(RequiresLogin at) { - this.checkLogin(); - } - - /** - * 根据注解(@RequiresRoles)鉴权 - * - * @param at 注解对象 - */ - public void checkByAnnotation(RequiresRoles at) { - String[] roleArray = at.value(); - if (at.logical() == Logical.AND) { - this.checkRoleAnd(roleArray); - } else { - this.checkRoleOr(roleArray); - } - } - - /** - * 根据注解(@RequiresPermissions)鉴权 - * - * @param at 注解对象 - */ - public void checkByAnnotation(RequiresPermissions at) { - String[] permissionArray = at.value(); - if (at.logical() == Logical.AND) { - this.checkPermiAnd(permissionArray); - } else { - this.checkPermiOr(permissionArray); - } - } - - /** - * 获取当前账号的角色列表 - * - * @return 角色列表 - */ - public Set getRoleList() { - try { - LoginUser loginUser = getLoginUser(); - return loginUser.getRoles(); - } catch (Exception e) { - return new HashSet<>(); - } - } - - /** - * 获取当前账号的权限列表 - * - * @return 权限列表 - */ - public Set getPermiList() { - try { - LoginUser loginUser = getLoginUser(); - return loginUser.getPermissions(); - } catch (Exception e) { - return new HashSet<>(); - } - } - - /** - * 判断是否包含权限 - * - * @param authorities 权限列表 - * @param permission 权限字符串 - * @return 用户是否具备某权限 - */ - public boolean hasPermi(Collection authorities, String permission) { - return authorities.stream().filter(StringUtils::isNotBlank) - .anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(x, permission)); - } - - /** - * 判断是否包含角色 - * - * @param roles 角色列表 - * @param role 角色 - * @return 用户是否具备某角色权限 - */ - public boolean hasRole(Collection roles, String role) { - return roles.stream().filter(StringUtils::isNotBlank) - .anyMatch(x -> SUPER_ADMIN.contains(x) || PatternMatchUtils.simpleMatch(x, role)); - } -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/auth/AuthUtil.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/auth/AuthUtil.java deleted file mode 100644 index 0a2aa4aa6..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/auth/AuthUtil.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.ruoyi.common.security.auth; - -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.annotation.RequiresRoles; -import com.ruoyi.system.api.model.LoginUser; - -/** - * Token 权限验证工具类 - * - * @author ruoyi - */ -public class AuthUtil { - /** - * 底层的 AuthLogic 对象 - */ - public static AuthLogic authLogic = new AuthLogic(); - - /** - * 会话注销 - */ - public static void logout() { - authLogic.logout(); - } - - /** - * 会话注销,根据指定Token - * - * @param tokenValue 指定token - */ - public static void logoutByToken(String token) { - authLogic.logoutByToken(token); - } - - /** - * 检验当前会话是否已经登录,如未登录,则抛出异常 - */ - public static void checkLogin() { - authLogic.checkLogin(); - } - - /** - * 获取当前登录用户信息 - */ - public static LoginUser getLoginUser(String token) { - return authLogic.getLoginUser(token); - } - - /** - * 验证当前用户有效期 - */ - public static void verifyLoginUserExpire(LoginUser loginUser) { - authLogic.verifyLoginUserExpire(loginUser); - } - - /** - * 当前账号是否含有指定角色标识, 返回true或false - * - * @param role 角色标识 - * @return 是否含有指定角色标识 - */ - public static boolean hasRole(String role) { - return authLogic.hasRole(role); - } - - /** - * 当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException - * - * @param role 角色标识 - */ - public static void checkRole(String role) { - authLogic.checkRole(role); - } - - /** - * 根据注解传入参数鉴权, 如果验证未通过,则抛出异常: NotRoleException - * - * @param requiresRoles 角色权限注解 - */ - public static void checkRole(RequiresRoles requiresRoles) { - authLogic.checkRole(requiresRoles); - } - - /** - * 当前账号是否含有指定角色标识 [指定多个,必须全部验证通过] - * - * @param roles 角色标识数组 - */ - public static void checkRoleAnd(String... roles) { - authLogic.checkRoleAnd(roles); - } - - /** - * 当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] - * - * @param roles 角色标识数组 - */ - public static void checkRoleOr(String... roles) { - authLogic.checkRoleOr(roles); - } - - /** - * 当前账号是否含有指定权限, 返回true或false - * - * @param permission 权限码 - * @return 是否含有指定权限 - */ - public static boolean hasPermi(String permission) { - return authLogic.hasPermi(permission); - } - - /** - * 当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException - * - * @param permission 权限码 - */ - public static void checkPermi(String permission) { - authLogic.checkPermi(permission); - } - - /** - * 根据注解传入参数鉴权, 如果验证未通过,则抛出异常: NotPermissionException - * - * @param requiresPermissions 权限注解 - */ - public static void checkPermi(RequiresPermissions requiresPermissions) { - authLogic.checkPermi(requiresPermissions); - } - - /** - * 当前账号是否含有指定权限 [指定多个,必须全部验证通过] - * - * @param permissions 权限码数组 - */ - public static void checkPermiAnd(String... permissions) { - authLogic.checkPermiAnd(permissions); - } - - /** - * 当前账号是否含有指定权限 [指定多个,只要其一验证通过即可] - * - * @param permissions 权限码数组 - */ - public static void checkPermiOr(String... permissions) { - authLogic.checkPermiOr(permissions); - } -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfiguration.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfiguration.java new file mode 100644 index 000000000..7d5a50483 --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfiguration.java @@ -0,0 +1,59 @@ +package com.ruoyi.common.security.config; + +import cn.dev33.satoken.filter.SaServletFilter; +import cn.dev33.satoken.id.SaIdUtil; +import cn.dev33.satoken.interceptor.SaAnnotationInterceptor; +import cn.dev33.satoken.interceptor.SaRouteInterceptor; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.util.SaResult; +import com.ruoyi.common.core.constant.HttpStatus; +import com.ruoyi.common.satoken.utils.LoginHelper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Sa-Token 整合 jwt (Style模式) + * + * @author Lion Li + */ +@Configuration +public class SecurityConfiguration implements WebMvcConfigurer { + + /** + * 注册sa-token的拦截器 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册路由拦截器,自定义验证规则 + // 这里只处理登录缓存清理 具体拦截再网关处理 + registry.addInterceptor(new SaRouteInterceptor((request, response, handler) -> { + // 获取所有的 + SaRouter.match("/**"); + }) { + @SuppressWarnings("all") + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + LoginHelper.clearCache(); + } + }).addPathPatterns("/**"); + // 注解拦截器 + registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**"); + } + + /** + * 校验是否从网关转发 + */ + @Bean + public SaServletFilter getSaServletFilter() { + return new SaServletFilter() + .addInclude("/**") + .setAuth(obj -> SaIdUtil.checkCurrentRequestToken()) + .setError(e -> SaResult.error("认证失败,无法访问系统资源").setCode(HttpStatus.UNAUTHORIZED)); + } + +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/WebMvcConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/WebMvcConfig.java deleted file mode 100644 index 75438ea45..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/WebMvcConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ruoyi.common.security.config; - -import com.ruoyi.common.security.interceptor.HeaderInterceptor; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -/** - * 拦截器配置 - * - * @author ruoyi - */ -public class WebMvcConfig implements WebMvcConfigurer { - /** - * 不需要拦截地址 - */ - public static final String[] excludeUrls = {"/login", "/logout", "/refresh"}; - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(getHeaderInterceptor()) - .addPathPatterns("/**") - .excludePathPatterns(excludeUrls) - .order(-10); - } - - /** - * 自定义请求头拦截器 - */ - public HeaderInterceptor getHeaderInterceptor() { - return new HeaderInterceptor(); - } -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/DubboAutoConfiguration.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/DubboAutoConfiguration.java deleted file mode 100644 index 8acc23f72..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/DubboAutoConfiguration.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ruoyi.common.security.feign; - -/** - * Feign 配置注册 - * - * @author ruoyi - **/ -//@Configuration -//public class DubboAutoConfiguration { -// @Bean -// public Filter requestInterceptor() { -// return new DubboRequestFilter(); -// } -//} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/DubboRequestFilter.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/DubboRequestFilter.java deleted file mode 100644 index 56fdfdd15..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/DubboRequestFilter.java +++ /dev/null @@ -1,49 +0,0 @@ -//package com.ruoyi.common.security.feign; -// -//import com.ruoyi.common.core.constant.SecurityConstants; -//import com.ruoyi.common.core.utils.ServletUtils; -//import com.ruoyi.common.core.utils.StringUtils; -//import com.ruoyi.common.core.utils.ip.IpUtils; -//import org.apache.dubbo.common.constants.CommonConstants; -//import org.apache.dubbo.common.extension.Activate; -//import org.apache.dubbo.rpc.*; -//import org.springframework.stereotype.Component; -// -//import javax.servlet.http.HttpServletRequest; -//import java.util.Map; -// -///** -// * feign 请求拦截器 -// * -// * @author ruoyi -// */ -//@Activate(group = {CommonConstants.CONSUMER}, order = -10000) -//@Component -//public class DubboRequestFilter implements Filter { -// @Override -// public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { -// //执行接口调用逻辑 -// Result result = invoker.invoke(invocation); -// HttpServletRequest httpServletRequest = ServletUtils.getRequest(); -// if (httpServletRequest != null) { -// Map headers = ServletUtils.getHeaders(httpServletRequest); -// // 传递用户信息请求头,防止丢失 -// String userId = headers.get(SecurityConstants.DETAILS_USER_ID); -// if (StringUtils.isNotEmpty(userId)) { -// RpcContext.getServerContext().setAttachment(SecurityConstants.DETAILS_USER_ID, userId); -// } -// String userName = headers.get(SecurityConstants.DETAILS_USERNAME); -// if (StringUtils.isNotEmpty(userName)) { -// RpcContext.getServerContext().setAttachment(SecurityConstants.DETAILS_USERNAME, userName); -// } -// String authentication = headers.get(SecurityConstants.AUTHORIZATION_HEADER); -// if (StringUtils.isNotEmpty(authentication)) { -// RpcContext.getServerContext().setAttachment(SecurityConstants.AUTHORIZATION_HEADER, authentication); -// } -// -// // 配置客户端IP -// RpcContext.getServerContext().setAttachment("X-Forwarded-For", IpUtils.getIpAddr(ServletUtils.getRequest())); -// } -// return result; -// } -//} \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java index 83a8a2433..2d89c3bbd 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java @@ -1,12 +1,13 @@ package com.ruoyi.common.security.handler; +import cn.dev33.satoken.exception.IdTokenInvalidException; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.exception.NotPermissionException; +import cn.dev33.satoken.exception.NotRoleException; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.exception.DemoModeException; -import com.ruoyi.common.core.exception.InnerAuthException; import com.ruoyi.common.core.exception.ServiceException; -import com.ruoyi.common.core.exception.auth.NotPermissionException; -import com.ruoyi.common.core.exception.auth.NotRoleException; import com.ruoyi.common.core.web.domain.AjaxResult; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindException; @@ -46,6 +47,26 @@ public class GlobalExceptionHandler { return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权"); } + /** + * 认证失败 + */ + @ExceptionHandler(NotLoginException.class) + public AjaxResult handleNotLoginException(NotLoginException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); + return AjaxResult.error(HttpStatus.UNAUTHORIZED, "认证失败,无法访问系统资源"); + } + + /** + * 无效认证 + */ + @ExceptionHandler(IdTokenInvalidException.class) + public AjaxResult handleIdTokenInvalidException(IdTokenInvalidException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',内网认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); + return AjaxResult.error(HttpStatus.UNAUTHORIZED, "认证失败,无法访问系统资源"); + } + /** * 请求方式不支持 */ @@ -107,14 +128,6 @@ public class GlobalExceptionHandler { return AjaxResult.error(message); } - /** - * 内部认证异常 - */ - @ExceptionHandler(InnerAuthException.class) - public AjaxResult handleInnerAuthException(InnerAuthException e) { - return AjaxResult.error(e.getMessage()); - } - /** * 演示模式异常 */ diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/interceptor/HeaderInterceptor.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/interceptor/HeaderInterceptor.java deleted file mode 100644 index 854cc5a08..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/interceptor/HeaderInterceptor.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ruoyi.common.security.interceptor; - -import cn.hutool.core.util.ObjectUtil; -import com.ruoyi.common.core.constant.SecurityConstants; -import com.ruoyi.common.core.context.SecurityContextHolder; -import com.ruoyi.common.core.utils.ServletUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.security.auth.AuthUtil; -import com.ruoyi.common.security.utils.SecurityUtils; -import com.ruoyi.system.api.model.LoginUser; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.AsyncHandlerInterceptor; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * 自定义请求头拦截器,将Header数据封装到线程变量中方便获取 - * 注意:此拦截器会同时验证当前用户有效期自动刷新有效期 - * - * @author ruoyi - */ -public class HeaderInterceptor implements AsyncHandlerInterceptor { - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - if (!(handler instanceof HandlerMethod)) { - return true; - } - - SecurityContextHolder.setUserId(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USER_ID)); - SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME)); - SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY)); - - String token = SecurityUtils.getToken(); - if (StringUtils.isNotEmpty(token)) { - LoginUser loginUser = AuthUtil.getLoginUser(token); - if (ObjectUtil.isNotNull(loginUser)) { - AuthUtil.verifyLoginUserExpire(loginUser); - SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser); - } - } - return true; - } - - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) - throws Exception { - SecurityContextHolder.remove(); - } -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java deleted file mode 100644 index 431a6ee0f..000000000 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.ruoyi.common.security.service; - -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.ObjectUtil; -import com.ruoyi.common.core.constant.CacheConstants; -import com.ruoyi.common.core.constant.SecurityConstants; -import com.ruoyi.common.core.utils.JwtUtils; -import com.ruoyi.common.core.utils.ServletUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.redis.utils.RedisUtils; -import com.ruoyi.common.security.utils.SecurityUtils; -import com.ruoyi.system.api.model.LoginUser; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * token验证处理 - * - * @author ruoyi - */ -@Component -public class TokenService { - - protected static final long MILLIS_SECOND = 1000; - - protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; - - private final static long expireTime = CacheConstants.EXPIRATION; - - private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY; - - private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE; - - /** - * 创建令牌 - */ - public Map createToken(LoginUser loginUser) { - String token = IdUtil.fastUUID(); - Long userId = loginUser.getSysUser().getUserId(); - String userName = loginUser.getSysUser().getUserName(); - loginUser.setToken(token); - loginUser.setUserid(userId); - loginUser.setUsername(userName); - loginUser.setIpaddr(ServletUtils.getClientIP()); - refreshToken(loginUser); - - // Jwt存储信息 - Map claimsMap = new HashMap(); - claimsMap.put(SecurityConstants.USER_KEY, token); - claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); - claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); - - // 接口返回信息 - Map rspMap = new HashMap(); - rspMap.put("access_token", JwtUtils.createToken(claimsMap)); - rspMap.put("expires_in", expireTime); - return rspMap; - } - - /** - * 获取用户身份信息 - * - * @return 用户信息 - */ - public LoginUser getLoginUser() { - return getLoginUser(ServletUtils.getRequest()); - } - - /** - * 获取用户身份信息 - * - * @return 用户信息 - */ - public LoginUser getLoginUser(HttpServletRequest request) { - // 获取请求携带的令牌 - String token = SecurityUtils.getToken(request); - return getLoginUser(token); - } - - /** - * 获取用户身份信息 - * - * @return 用户信息 - */ - public LoginUser getLoginUser(String token) { - LoginUser user = null; - try { - if (StringUtils.isNotEmpty(token)) { - String userkey = JwtUtils.getUserKey(token); - user = RedisUtils.getCacheObject(getTokenKey(userkey)); - return user; - } - } catch (Exception e) { - } - return user; - } - - /** - * 设置用户身份信息 - */ - public void setLoginUser(LoginUser loginUser) { - if (ObjectUtil.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) { - refreshToken(loginUser); - } - } - - /** - * 删除用户缓存信息 - */ - public void delLoginUser(String token) { - if (StringUtils.isNotEmpty(token)) { - String userkey = JwtUtils.getUserKey(token); - RedisUtils.deleteObject(getTokenKey(userkey)); - } - } - - /** - * 验证令牌有效期,相差不足120分钟,自动刷新缓存 - * - * @param loginUser - */ - public void verifyToken(LoginUser loginUser) { - long expireTime = loginUser.getExpireTime(); - long currentTime = System.currentTimeMillis(); - if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { - refreshToken(loginUser); - } - } - - /** - * 刷新令牌有效期 - * - * @param loginUser 登录信息 - */ - public void refreshToken(LoginUser loginUser) { - loginUser.setLoginTime(System.currentTimeMillis()); - loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); - // 根据uuid将loginUser缓存 - String userKey = getTokenKey(loginUser.getToken()); - RedisUtils.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); - } - - private String getTokenKey(String token) { - return ACCESS_TOKEN + token; - } -} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java index 34c406bca..6d7c8c1ac 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java @@ -1,75 +1,16 @@ package com.ruoyi.common.security.utils; -import com.ruoyi.common.core.constant.SecurityConstants; -import com.ruoyi.common.core.constant.TokenConstants; -import com.ruoyi.common.core.context.SecurityContextHolder; -import com.ruoyi.common.core.utils.ServletUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.system.api.model.LoginUser; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import javax.servlet.http.HttpServletRequest; - /** * 权限获取工具类 * * @author ruoyi */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class SecurityUtils { - /** - * 获取用户ID - */ - public static Long getUserId() { - return SecurityContextHolder.getUserId(); - } - - /** - * 获取用户名称 - */ - public static String getUsername() { - return SecurityContextHolder.getUserName(); - } - - /** - * 获取用户key - */ - public static String getUserKey() { - return SecurityContextHolder.getUserKey(); - } - - /** - * 获取登录用户信息 - */ - public static LoginUser getLoginUser() { - return SecurityContextHolder.get(SecurityConstants.LOGIN_USER, LoginUser.class); - } - - /** - * 获取请求token - */ - public static String getToken() { - return getToken(ServletUtils.getRequest()); - } - - /** - * 根据request获取请求token - */ - public static String getToken(HttpServletRequest request) { - // 从header获取token标识 - String token = request.getHeader(TokenConstants.AUTHENTICATION); - return replaceTokenPrefix(token); - } - - /** - * 裁剪token前缀 - */ - public static String replaceTokenPrefix(String token) { - // 如果前端设置了令牌前缀,则裁剪掉前缀 - if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) { - token = token.replaceFirst(TokenConstants.PREFIX, ""); - } - return token; - } /** * 是否为管理员 diff --git a/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring.factories b/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring.factories index 0158210b3..92e852ff5 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring.factories +++ b/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring.factories @@ -1,6 +1,3 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.ruoyi.common.security.config.WebMvcConfig,\ - com.ruoyi.common.security.service.TokenService,\ - com.ruoyi.common.security.aspect.PreAuthorizeAspect,\ - com.ruoyi.common.security.aspect.InnerAuthAspect,\ - com.ruoyi.common.security.handler.GlobalExceptionHandler +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.ruoyi.common.security.handler.GlobalExceptionHandler,\ + com.ruoyi.common.security.config.SecurityConfiguration diff --git a/ruoyi-gateway/pom.xml b/ruoyi-gateway/pom.xml index dddf6c521..e1938e717 100644 --- a/ruoyi-gateway/pom.xml +++ b/ruoyi-gateway/pom.xml @@ -63,6 +63,28 @@ spring-boot-starter-actuator + + cn.hutool + hutool-captcha + + + + cn.hutool + hutool-http + + + + + cn.dev33 + sa-token-reactor-spring-boot-starter + ${satoken.version} + + + + com.ruoyi + ruoyi-common-satoken + + com.ruoyi @@ -75,15 +97,6 @@ - - cn.hutool - hutool-captcha - - - - cn.hutool - hutool-http - diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java index 9dd6703be..972e04a6f 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java @@ -1,117 +1,34 @@ package com.ruoyi.gateway.filter; -import cn.hutool.json.JSONObject; -import com.ruoyi.common.core.constant.CacheConstants; +import cn.dev33.satoken.reactor.filter.SaReactorFilter; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; import com.ruoyi.common.core.constant.HttpStatus; -import com.ruoyi.common.core.constant.SecurityConstants; -import com.ruoyi.common.core.constant.TokenConstants; -import com.ruoyi.common.core.utils.JwtUtils; -import com.ruoyi.common.core.utils.ServletUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.redis.utils.RedisUtils; import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties; -import com.ruoyi.gateway.utils.WebFluxUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.core.Ordered; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; /** - * 网关鉴权 - * - * @author ruoyi + * [Sa-Token 权限认证] 拦截器 + * @author Lion Li */ -@Component -public class AuthFilter implements GlobalFilter, Ordered { - private static final Logger log = LoggerFactory.getLogger(AuthFilter.class); +@Configuration +public class AuthFilter { - // 排除过滤的 uri 地址,nacos自行添加 - @Autowired - private IgnoreWhiteProperties ignoreWhite; - - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - ServerHttpRequest request = exchange.getRequest(); - ServerHttpRequest.Builder mutate = request.mutate(); - - String url = request.getURI().getPath(); - // 跳过不需要验证的路径 - if (StringUtils.matches(url, ignoreWhite.getWhites())) { - return chain.filter(exchange); - } - String token = getToken(request); - if (StringUtils.isEmpty(token)) { - return unauthorizedResponse(exchange, "令牌不能为空"); - } - JSONObject claims = JwtUtils.parseToken(token); - if (claims == null) { - return unauthorizedResponse(exchange, "令牌已过期或验证不正确!"); - } - String userkey = JwtUtils.getUserKey(claims); - boolean islogin = RedisUtils.hasKey(getTokenKey(userkey)); - if (!islogin) { - return unauthorizedResponse(exchange, "登录状态已过期"); - } - String userid = JwtUtils.getUserId(claims); - String username = JwtUtils.getUserName(claims); - if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username)) { - return unauthorizedResponse(exchange, "令牌验证失败"); - } - - // 设置用户信息到请求 - addHeader(mutate, SecurityConstants.USER_KEY, userkey); - addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid); - addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username); - // 内部请求来源参数清除 - removeHeader(mutate, SecurityConstants.FROM_SOURCE); - return chain.filter(exchange.mutate().request(mutate.build()).build()); + // 注册 Sa-Token全局过滤器 + @Bean + public SaReactorFilter getSaReactorFilter(IgnoreWhiteProperties ignoreWhite) { + return new SaReactorFilter() + // 拦截地址 + .addInclude("/**") + // 开放地址 + .setExcludeList(ignoreWhite.getWhites()) + .addExclude("/favicon.ico") + // 鉴权方法:每次访问进入 + .setAuth(obj -> { + // 登录校验 -- 拦截所有路由 + SaRouter.match("/**", r -> StpUtil.checkLogin()); + }).setError(e -> SaResult.error("认证失败,无法访问系统资源").setCode(HttpStatus.UNAUTHORIZED)); } - - private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) { - if (value == null) { - return; - } - String valueStr = value.toString(); - String valueEncode = ServletUtils.urlEncode(valueStr); - mutate.header(name, valueEncode); - } - - private void removeHeader(ServerHttpRequest.Builder mutate, String name) { - mutate.headers(httpHeaders -> httpHeaders.remove(name)).build(); - } - - private Mono unauthorizedResponse(ServerWebExchange exchange, String msg) { - log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath()); - return WebFluxUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED); - } - - /** - * 获取缓存key - */ - private String getTokenKey(String token) { - return CacheConstants.LOGIN_TOKEN_KEY + token; - } - - /** - * 获取请求token - */ - private String getToken(ServerHttpRequest request) { - String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION); - // 如果前端设置了令牌前缀,则裁剪掉前缀 - if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) { - token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY); - } - return token; - } - - @Override - public int getOrder() { - return -200; - } -} \ No newline at end of file +} diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ForwardAuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ForwardAuthFilter.java new file mode 100644 index 000000000..45661bf98 --- /dev/null +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ForwardAuthFilter.java @@ -0,0 +1,30 @@ +package com.ruoyi.gateway.filter; + +import cn.dev33.satoken.id.SaIdUtil; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * 转发认证过滤器(内部服务外网隔离) + * + * @author Lion Li + */ +@Component +public class ForwardAuthFilter implements GlobalFilter { + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest newRequest = exchange + .getRequest() + .mutate() + // 为请求追加 Id-Token 参数 + .header(SaIdUtil.ID_TOKEN, SaIdUtil.getToken()) + .build(); + ServerWebExchange newExchange = exchange.mutate().request(newRequest).build(); + return chain.filter(newExchange); + } +} + diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java index c54025c79..bdd726150 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java @@ -1,99 +1,99 @@ -package com.ruoyi.gateway.service.impl; - -import cn.hutool.captcha.AbstractCaptcha; -import cn.hutool.captcha.generator.CodeGenerator; -import cn.hutool.core.convert.Convert; -import cn.hutool.core.util.IdUtil; -import com.ruoyi.common.core.constant.Constants; -import com.ruoyi.common.core.exception.CaptchaException; -import com.ruoyi.common.core.utils.SpringUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.core.utils.reflect.ReflectUtils; -import com.ruoyi.common.core.web.domain.AjaxResult; -import com.ruoyi.common.redis.utils.RedisUtils; -import com.ruoyi.gateway.config.properties.CaptchaProperties; -import com.ruoyi.gateway.enums.CaptchaType; -import com.ruoyi.gateway.service.ValidateCodeService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -/** - * 验证码实现处理 - * - * @author ruoyi - */ -@Service -public class ValidateCodeServiceImpl implements ValidateCodeService { - @Autowired - private CaptchaProperties captchaProperties; - - /** - * 生成验证码 - */ - @Override - public AjaxResult createCapcha() throws IOException, CaptchaException { - AjaxResult ajax = AjaxResult.success(); - boolean captchaOnOff = captchaProperties.getEnabled(); - ajax.put("captchaOnOff", captchaOnOff); - if (!captchaOnOff) { - return ajax; - } - - // 保存验证码信息 - String uuid = IdUtil.simpleUUID(); - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; - // 生成验证码 - CaptchaType captchaType = captchaProperties.getType(); - boolean isMath = CaptchaType.MATH == captchaType; - Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength(); - CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length); - AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz()); - captcha.setGenerator(codeGenerator); - captcha.createCode(); - String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode(); - RedisUtils.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); - ajax.put("uuid", uuid); - ajax.put("img", captcha.getImageBase64()); - return ajax; - } - - private String getCodeResult(String capStr) { - int numberLength = captchaProperties.getNumberLength(); - int a = Convert.toInt(StringUtils.substring(capStr, 0, numberLength).trim()); - char operator = capStr.charAt(numberLength); - int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim()); - switch (operator) { - case '*': - return Convert.toStr(a * b); - case '+': - return Convert.toStr(a + b); - case '-': - return Convert.toStr(a - b); - default: - return StringUtils.EMPTY; - } - } - - /** - * 校验验证码 - */ - @Override - public void checkCapcha(String code, String uuid) throws CaptchaException { - if (StringUtils.isEmpty(code)) { - throw new CaptchaException("验证码不能为空"); - } - if (StringUtils.isEmpty(uuid)) { - throw new CaptchaException("验证码已失效"); - } - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; - String captcha = RedisUtils.getCacheObject(verifyKey); - RedisUtils.deleteObject(verifyKey); - - if (!code.equalsIgnoreCase(captcha)) { - throw new CaptchaException("验证码错误"); - } - } -} +package com.ruoyi.gateway.service.impl; + +import cn.hutool.captcha.AbstractCaptcha; +import cn.hutool.captcha.generator.CodeGenerator; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.IdUtil; +import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.exception.CaptchaException; +import com.ruoyi.common.core.utils.SpringUtils; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.utils.reflect.ReflectUtils; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.redis.utils.RedisUtils; +import com.ruoyi.gateway.config.properties.CaptchaProperties; +import com.ruoyi.gateway.enums.CaptchaType; +import com.ruoyi.gateway.service.ValidateCodeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * 验证码实现处理 + * + * @author ruoyi + */ +@Service +public class ValidateCodeServiceImpl implements ValidateCodeService { + @Autowired + private CaptchaProperties captchaProperties; + + /** + * 生成验证码 + */ + @Override + public AjaxResult createCapcha() throws IOException, CaptchaException { + AjaxResult ajax = AjaxResult.success(); + boolean captchaOnOff = captchaProperties.getEnabled(); + ajax.put("captchaOnOff", captchaOnOff); + if (!captchaOnOff) { + return ajax; + } + + // 保存验证码信息 + String uuid = IdUtil.simpleUUID(); + String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + // 生成验证码 + CaptchaType captchaType = captchaProperties.getType(); + boolean isMath = CaptchaType.MATH == captchaType; + Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength(); + CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length); + AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz()); + captcha.setGenerator(codeGenerator); + captcha.createCode(); + String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode(); + RedisUtils.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); + ajax.put("uuid", uuid); + ajax.put("img", captcha.getImageBase64()); + return ajax; + } + + private String getCodeResult(String capStr) { + int numberLength = captchaProperties.getNumberLength(); + int a = Convert.toInt(StringUtils.substring(capStr, 0, numberLength).trim()); + char operator = capStr.charAt(numberLength); + int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim()); + switch (operator) { + case '*': + return Convert.toStr(a * b); + case '+': + return Convert.toStr(a + b); + case '-': + return Convert.toStr(a - b); + default: + return StringUtils.EMPTY; + } + } + + /** + * 校验验证码 + */ + @Override + public void checkCapcha(String code, String uuid) throws CaptchaException { + if (StringUtils.isEmpty(code)) { + throw new CaptchaException("验证码不能为空"); + } + if (StringUtils.isEmpty(uuid)) { + throw new CaptchaException("验证码已失效"); + } + String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + String captcha = RedisUtils.getCacheObject(verifyKey); + RedisUtils.deleteObject(verifyKey); + + if (!code.equalsIgnoreCase(captcha)) { + throw new CaptchaException("验证码错误"); + } + } +} diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/RuoYiGenApplication.java b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/RuoYiGenApplication.java index b8e6d998f..db874097d 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/RuoYiGenApplication.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/RuoYiGenApplication.java @@ -1,21 +1,21 @@ -package com.ruoyi.gen; - -import com.ruoyi.common.security.annotation.EnableCustomConfig; -import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * 代码生成 - * - * @author ruoyi - */ -@EnableCustomConfig -@EnableDubbo -@SpringBootApplication -public class RuoYiGenApplication { - public static void main(String[] args) { - SpringApplication.run(RuoYiGenApplication.class, args); - System.out.println("(♥◠‿◠)ノ゙ 代码生成模块启动成功 ლ(´ڡ`ლ)゙ "); - } -} +package com.ruoyi.gen; + +import com.ruoyi.common.security.annotation.EnableCustomConfig; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * 代码生成 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableDubbo +@SpringBootApplication +public class RuoYiGenApplication { + public static void main(String[] args) { + SpringApplication.run(RuoYiGenApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 代码生成模块启动成功 ლ(´ڡ`ლ)゙ "); + } +} diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/controller/GenController.java b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/controller/GenController.java index 54c9da6ea..64a611664 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/controller/GenController.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/controller/GenController.java @@ -1,5 +1,6 @@ package com.ruoyi.gen.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.IoUtil; import com.ruoyi.common.core.web.controller.BaseController; @@ -8,7 +9,6 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.gen.domain.GenTable; import com.ruoyi.gen.domain.GenTableColumn; import com.ruoyi.gen.service.IGenTableColumnService; @@ -41,7 +41,7 @@ public class GenController extends BaseController { /** * 查询代码生成列表 */ - @RequiresPermissions("tool:gen:list") + @SaCheckPermission("tool:gen:list") @GetMapping("/list") public TableDataInfo genList(GenTable genTable, PageQuery pageQuery) { return genTableService.selectPageGenTableList(genTable, pageQuery); @@ -50,7 +50,7 @@ public class GenController extends BaseController { /** * 修改代码生成业务 */ - @RequiresPermissions("tool:gen:query") + @SaCheckPermission("tool:gen:query") @GetMapping(value = "/{talbleId}") public AjaxResult getInfo(@PathVariable Long talbleId) { GenTable table = genTableService.selectGenTableById(talbleId); @@ -66,7 +66,7 @@ public class GenController extends BaseController { /** * 查询数据库列表 */ - @RequiresPermissions("tool:gen:list") + @SaCheckPermission("tool:gen:list") @GetMapping("/db/list") public TableDataInfo dataList(GenTable genTable, PageQuery pageQuery) { return genTableService.selectPageDbTableList(genTable, pageQuery); @@ -87,7 +87,7 @@ public class GenController extends BaseController { /** * 导入表结构(保存) */ - @RequiresPermissions("tool:gen:import") + @SaCheckPermission("tool:gen:import") @Log(title = "代码生成", businessType = BusinessType.IMPORT) @PostMapping("/importTable") public AjaxResult importTableSave(String tables) { @@ -101,7 +101,7 @@ public class GenController extends BaseController { /** * 修改保存代码生成业务 */ - @RequiresPermissions("tool:gen:edit") + @SaCheckPermission("tool:gen:edit") @Log(title = "代码生成", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult editSave(@Validated @RequestBody GenTable genTable) { @@ -113,7 +113,7 @@ public class GenController extends BaseController { /** * 删除代码生成 */ - @RequiresPermissions("tool:gen:remove") + @SaCheckPermission("tool:gen:remove") @Log(title = "代码生成", businessType = BusinessType.DELETE) @DeleteMapping("/{tableIds}") public AjaxResult remove(@PathVariable Long[] tableIds) { @@ -124,7 +124,7 @@ public class GenController extends BaseController { /** * 预览代码 */ - @RequiresPermissions("tool:gen:preview") + @SaCheckPermission("tool:gen:preview") @GetMapping("/preview/{tableId}") public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException { Map dataMap = genTableService.previewCode(tableId); @@ -134,7 +134,7 @@ public class GenController extends BaseController { /** * 生成代码(下载方式) */ - @RequiresPermissions("tool:gen:code") + @SaCheckPermission("tool:gen:code") @Log(title = "代码生成", businessType = BusinessType.GENCODE) @GetMapping("/download/{tableName}") public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException { @@ -145,7 +145,7 @@ public class GenController extends BaseController { /** * 生成代码(自定义路径) */ - @RequiresPermissions("tool:gen:code") + @SaCheckPermission("tool:gen:code") @Log(title = "代码生成", businessType = BusinessType.GENCODE) @GetMapping("/genCode/{tableName}") public AjaxResult genCode(@PathVariable("tableName") String tableName) { @@ -156,7 +156,7 @@ public class GenController extends BaseController { /** * 同步数据库 */ - @RequiresPermissions("tool:gen:edit") + @SaCheckPermission("tool:gen:edit") @Log(title = "代码生成", businessType = BusinessType.UPDATE) @GetMapping("/synchDb/{tableName}") public AjaxResult synchDb(@PathVariable("tableName") String tableName) { @@ -167,7 +167,7 @@ public class GenController extends BaseController { /** * 批量生成代码 */ - @RequiresPermissions("tool:gen:code") + @SaCheckPermission("tool:gen:code") @Log(title = "代码生成", businessType = BusinessType.GENCODE) @GetMapping("/batchGenCode") public void batchGenCode(HttpServletResponse response, String tables) throws IOException { diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java index 61e5f0b7f..390c209ad 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java @@ -12,7 +12,7 @@ import com.ruoyi.common.core.utils.JsonUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.gen.domain.GenTable; import com.ruoyi.gen.domain.GenTableColumn; import com.ruoyi.gen.mapper.GenTableColumnMapper; @@ -163,7 +163,7 @@ public class GenTableServiceImpl implements IGenTableService { @Override @Transactional(rollbackFor = Exception.class) public void importGenTable(List tableList) { - String operName = SecurityUtils.getUsername(); + String operName = LoginHelper.getUsername(); try { for (GenTable table : tableList) { String tableName = table.getTableName(); diff --git a/ruoyi-modules/ruoyi-gen/src/main/resources/vm/java/controller.java.vm b/ruoyi-modules/ruoyi-gen/src/main/resources/vm/java/controller.java.vm index 3508058dd..bb6a43079 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/resources/vm/java/controller.java.vm +++ b/ruoyi-modules/ruoyi-gen/src/main/resources/vm/java/controller.java.vm @@ -40,7 +40,7 @@ public class ${ClassName}Controller extends BaseController /** * 查询${functionName}列表 */ - @RequiresPermissions("${permissionPrefix}:list") + @SaCheckPermission("${permissionPrefix}:list") @GetMapping("/list") #if($table.crud || $table.sub) public TableDataInfo list(${ClassName} ${className}) @@ -60,7 +60,7 @@ public class ${ClassName}Controller extends BaseController /** * 导出${functionName}列表 */ - @RequiresPermissions("${permissionPrefix}:export") + @SaCheckPermission("${permissionPrefix}:export") @Log(title = "${functionName}", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, ${ClassName} ${className}) @@ -73,7 +73,7 @@ public class ${ClassName}Controller extends BaseController /** * 获取${functionName}详细信息 */ - @RequiresPermissions("${permissionPrefix}:query") + @SaCheckPermission("${permissionPrefix}:query") @GetMapping(value = "/{${pkColumn.javaField}}") public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) { @@ -83,7 +83,7 @@ public class ${ClassName}Controller extends BaseController /** * 新增${functionName} */ - @RequiresPermissions("${permissionPrefix}:add") + @SaCheckPermission("${permissionPrefix}:add") @Log(title = "${functionName}", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody ${ClassName} ${className}) @@ -94,7 +94,7 @@ public class ${ClassName}Controller extends BaseController /** * 修改${functionName} */ - @RequiresPermissions("${permissionPrefix}:edit") + @SaCheckPermission("${permissionPrefix}:edit") @Log(title = "${functionName}", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody ${ClassName} ${className}) @@ -105,7 +105,7 @@ public class ${ClassName}Controller extends BaseController /** * 删除${functionName} */ - @RequiresPermissions("${permissionPrefix}:remove") + @SaCheckPermission("${permissionPrefix}:remove") @Log(title = "${functionName}", businessType = BusinessType.DELETE) @DeleteMapping("/{${pkColumn.javaField}s}") public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/RuoYiSystemApplication.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/RuoYiSystemApplication.java index f65a998cf..d83855e66 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/RuoYiSystemApplication.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/RuoYiSystemApplication.java @@ -1,21 +1,21 @@ -package com.ruoyi.system; - -import com.ruoyi.common.security.annotation.EnableCustomConfig; -import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * 系统模块 - * - * @author ruoyi - */ -@EnableCustomConfig -@EnableDubbo -@SpringBootApplication -public class RuoYiSystemApplication { - public static void main(String[] args) { - SpringApplication.run(RuoYiSystemApplication.class, args); - System.out.println("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙ "); - } -} +package com.ruoyi.system; + +import com.ruoyi.common.security.annotation.EnableCustomConfig; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * 系统模块 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableDubbo +@SpringBootApplication +public class RuoYiSystemApplication { + public static void main(String[] args) { + SpringApplication.run(RuoYiSystemApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙ "); + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java index a418f349f..ee57cbe52 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; @@ -8,8 +9,7 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.service.ISysConfigService; import lombok.RequiredArgsConstructor; @@ -34,14 +34,14 @@ public class SysConfigController extends BaseController { /** * 获取参数配置列表 */ - @RequiresPermissions("system:config:list") + @SaCheckPermission("system:config:list") @GetMapping("/list") public TableDataInfo list(SysConfig config, PageQuery pageQuery) { return configService.selectPageConfigList(config, pageQuery); } @Log(title = "参数管理", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:config:export") + @SaCheckPermission("system:config:export") @PostMapping("/export") public void export(HttpServletResponse response, SysConfig config) { List list = configService.selectConfigList(config); @@ -67,35 +67,35 @@ public class SysConfigController extends BaseController { /** * 新增参数配置 */ - @RequiresPermissions("system:config:add") + @SaCheckPermission("system:config:add") @Log(title = "参数管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysConfig config) { if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); } - config.setCreateBy(SecurityUtils.getUsername()); + config.setCreateBy(LoginHelper.getUsername()); return toAjax(configService.insertConfig(config)); } /** * 修改参数配置 */ - @RequiresPermissions("system:config:edit") + @SaCheckPermission("system:config:edit") @Log(title = "参数管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysConfig config) { if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); } - config.setUpdateBy(SecurityUtils.getUsername()); + config.setUpdateBy(LoginHelper.getUsername()); return toAjax(configService.updateConfig(config)); } /** * 删除参数配置 */ - @RequiresPermissions("system:config:remove") + @SaCheckPermission("system:config:remove") @Log(title = "参数管理", businessType = BusinessType.DELETE) @DeleteMapping("/{configIds}") public AjaxResult remove(@PathVariable Long[] configIds) { @@ -106,7 +106,7 @@ public class SysConfigController extends BaseController { /** * 刷新参数缓存 */ - @RequiresPermissions("system:config:remove") + @SaCheckPermission("system:config:remove") @Log(title = "参数管理", businessType = BusinessType.CLEAN) @DeleteMapping("/refreshCache") public AjaxResult refreshCache() { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java index 64db103ad..bcdf094de 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ArrayUtil; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.utils.StringUtils; @@ -7,8 +8,7 @@ import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.service.ISysDeptService; import lombok.RequiredArgsConstructor; @@ -32,7 +32,7 @@ public class SysDeptController extends BaseController { /** * 获取部门列表 */ - @RequiresPermissions("system:dept:list") + @SaCheckPermission("system:dept:list") @GetMapping("/list") public AjaxResult list(SysDept dept) { List depts = deptService.selectDeptList(dept); @@ -42,7 +42,7 @@ public class SysDeptController extends BaseController { /** * 查询部门列表(排除节点) */ - @RequiresPermissions("system:dept:list") + @SaCheckPermission("system:dept:list") @GetMapping("/list/exclude/{deptId}") public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) { List depts = deptService.selectDeptList(new SysDept()); @@ -54,7 +54,7 @@ public class SysDeptController extends BaseController { /** * 根据部门编号获取详细信息 */ - @RequiresPermissions("system:dept:query") + @SaCheckPermission("system:dept:query") @GetMapping(value = "/{deptId}") public AjaxResult getInfo(@PathVariable Long deptId) { deptService.checkDeptDataScope(deptId); @@ -85,21 +85,21 @@ public class SysDeptController extends BaseController { /** * 新增部门 */ - @RequiresPermissions("system:dept:add") + @SaCheckPermission("system:dept:add") @Log(title = "部门管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysDept dept) { if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) { return AjaxResult.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); } - dept.setCreateBy(SecurityUtils.getUsername()); + dept.setCreateBy(LoginHelper.getUsername()); return toAjax(deptService.insertDept(dept)); } /** * 修改部门 */ - @RequiresPermissions("system:dept:edit") + @SaCheckPermission("system:dept:edit") @Log(title = "部门管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysDept dept) { @@ -111,14 +111,14 @@ public class SysDeptController extends BaseController { && deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0) { return AjaxResult.error("该部门包含未停用的子部门!"); } - dept.setUpdateBy(SecurityUtils.getUsername()); + dept.setUpdateBy(LoginHelper.getUsername()); return toAjax(deptService.updateDept(dept)); } /** * 删除部门 */ - @RequiresPermissions("system:dept:remove") + @SaCheckPermission("system:dept:remove") @Log(title = "部门管理", businessType = BusinessType.DELETE) @DeleteMapping("/{deptId}") public AjaxResult remove(@PathVariable Long deptId) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java index 84295e8e3..72f52da4f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; @@ -8,8 +9,7 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.domain.SysDictData; import com.ruoyi.system.service.ISysDictDataService; import com.ruoyi.system.service.ISysDictTypeService; @@ -34,14 +34,14 @@ public class SysDictDataController extends BaseController { private final ISysDictDataService dictDataService; private final ISysDictTypeService dictTypeService; - @RequiresPermissions("system:dict:list") + @SaCheckPermission("system:dict:list") @GetMapping("/list") public TableDataInfo list(SysDictData dictData, PageQuery pageQuery) { return dictDataService.selectPageDictDataList(dictData, pageQuery); } @Log(title = "字典数据", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:dict:export") + @SaCheckPermission("system:dict:export") @PostMapping("/export") public void export(HttpServletResponse response, SysDictData dictData) { List list = dictDataService.selectDictDataList(dictData); @@ -51,7 +51,7 @@ public class SysDictDataController extends BaseController { /** * 查询字典数据详细 */ - @RequiresPermissions("system:dict:query") + @SaCheckPermission("system:dict:query") @GetMapping(value = "/{dictCode}") public AjaxResult getInfo(@PathVariable Long dictCode) { return AjaxResult.success(dictDataService.selectDictDataById(dictCode)); @@ -72,29 +72,29 @@ public class SysDictDataController extends BaseController { /** * 新增字典类型 */ - @RequiresPermissions("system:dict:add") + @SaCheckPermission("system:dict:add") @Log(title = "字典数据", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysDictData dict) { - dict.setCreateBy(SecurityUtils.getUsername()); + dict.setCreateBy(LoginHelper.getUsername()); return toAjax(dictDataService.insertDictData(dict)); } /** * 修改保存字典类型 */ - @RequiresPermissions("system:dict:edit") + @SaCheckPermission("system:dict:edit") @Log(title = "字典数据", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysDictData dict) { - dict.setUpdateBy(SecurityUtils.getUsername()); + dict.setUpdateBy(LoginHelper.getUsername()); return toAjax(dictDataService.updateDictData(dict)); } /** * 删除字典类型 */ - @RequiresPermissions("system:dict:remove") + @SaCheckPermission("system:dict:remove") @Log(title = "字典类型", businessType = BusinessType.DELETE) @DeleteMapping("/{dictCodes}") public AjaxResult remove(@PathVariable Long[] dictCodes) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java index 22d4af95b..b7e4ca68c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; @@ -8,8 +9,7 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.domain.SysDictType; import com.ruoyi.system.service.ISysDictTypeService; import lombok.RequiredArgsConstructor; @@ -31,14 +31,14 @@ public class SysDictTypeController extends BaseController { private final ISysDictTypeService dictTypeService; - @RequiresPermissions("system:dict:list") + @SaCheckPermission("system:dict:list") @GetMapping("/list") public TableDataInfo list(SysDictType dictType, PageQuery pageQuery) { return dictTypeService.selectPageDictTypeList(dictType, pageQuery); } @Log(title = "字典类型", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:dict:export") + @SaCheckPermission("system:dict:export") @PostMapping("/export") public void export(HttpServletResponse response, SysDictType dictType) { List list = dictTypeService.selectDictTypeList(dictType); @@ -48,7 +48,7 @@ public class SysDictTypeController extends BaseController { /** * 查询字典类型详细 */ - @RequiresPermissions("system:dict:query") + @SaCheckPermission("system:dict:query") @GetMapping(value = "/{dictId}") public AjaxResult getInfo(@PathVariable Long dictId) { return AjaxResult.success(dictTypeService.selectDictTypeById(dictId)); @@ -57,35 +57,35 @@ public class SysDictTypeController extends BaseController { /** * 新增字典类型 */ - @RequiresPermissions("system:dict:add") + @SaCheckPermission("system:dict:add") @Log(title = "字典类型", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysDictType dict) { if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { return AjaxResult.error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); } - dict.setCreateBy(SecurityUtils.getUsername()); + dict.setCreateBy(LoginHelper.getUsername()); return toAjax(dictTypeService.insertDictType(dict)); } /** * 修改字典类型 */ - @RequiresPermissions("system:dict:edit") + @SaCheckPermission("system:dict:edit") @Log(title = "字典类型", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysDictType dict) { if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { return AjaxResult.error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); } - dict.setUpdateBy(SecurityUtils.getUsername()); + dict.setUpdateBy(LoginHelper.getUsername()); return toAjax(dictTypeService.updateDictType(dict)); } /** * 删除字典类型 */ - @RequiresPermissions("system:dict:remove") + @SaCheckPermission("system:dict:remove") @Log(title = "字典类型", businessType = BusinessType.DELETE) @DeleteMapping("/{dictIds}") public AjaxResult remove(@PathVariable Long[] dictIds) { @@ -96,7 +96,7 @@ public class SysDictTypeController extends BaseController { /** * 刷新字典缓存 */ - @RequiresPermissions("system:dict:remove") + @SaCheckPermission("system:dict:remove") @Log(title = "字典类型", businessType = BusinessType.CLEAN) @DeleteMapping("/refreshCache") public AjaxResult refreshCache() { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysLogininforController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysLogininforController.java index 1ed3949c4..e046fcd37 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysLogininforController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysLogininforController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.excel.utils.ExcelUtil; @@ -7,8 +8,6 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.InnerAuth; -import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.system.api.domain.SysLogininfor; import com.ruoyi.system.service.ISysLogininforService; import lombok.RequiredArgsConstructor; @@ -29,28 +28,28 @@ public class SysLogininforController extends BaseController { private final ISysLogininforService logininforService; - @RequiresPermissions("system:logininfor:list") + @SaCheckPermission("system:logininfor:list") @GetMapping("/list") public TableDataInfo list(SysLogininfor logininfor, PageQuery pageQuery) { return logininforService.selectPageLogininforList(logininfor, pageQuery); } @Log(title = "登录日志", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:logininfor:export") + @SaCheckPermission("system:logininfor:export") @PostMapping("/export") public void export(HttpServletResponse response, SysLogininfor logininfor) { List list = logininforService.selectLogininforList(logininfor); ExcelUtil.exportExcel(list, "登录日志", SysLogininfor.class, response); } - @RequiresPermissions("system:logininfor:remove") + @SaCheckPermission("system:logininfor:remove") @Log(title = "登录日志", businessType = BusinessType.DELETE) @DeleteMapping("/{infoIds}") public AjaxResult remove(@PathVariable Long[] infoIds) { return toAjax(logininforService.deleteLogininforByIds(infoIds)); } - @RequiresPermissions("system:logininfor:remove") + @SaCheckPermission("system:logininfor:remove") @Log(title = "登录日志", businessType = BusinessType.DELETE) @DeleteMapping("/clean") public AjaxResult clean() { @@ -58,7 +57,7 @@ public class SysLogininforController extends BaseController { return AjaxResult.success(); } - @InnerAuth +// @InnerAuth @PostMapping public AjaxResult add(@RequestBody SysLogininfor logininfor) { return toAjax(logininforService.insertLogininfor(logininfor)); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java index e345678ef..9d090d8fa 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java @@ -1,13 +1,13 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.domain.SysMenu; import com.ruoyi.system.service.ISysMenuService; import lombok.RequiredArgsConstructor; @@ -31,10 +31,10 @@ public class SysMenuController extends BaseController { /** * 获取菜单列表 */ - @RequiresPermissions("system:menu:list") + @SaCheckPermission("system:menu:list") @GetMapping("/list") public AjaxResult list(SysMenu menu) { - Long userId = SecurityUtils.getUserId(); + Long userId = LoginHelper.getUserId(); List menus = menuService.selectMenuList(menu, userId); return AjaxResult.success(menus); } @@ -42,7 +42,7 @@ public class SysMenuController extends BaseController { /** * 根据菜单编号获取详细信息 */ - @RequiresPermissions("system:menu:query") + @SaCheckPermission("system:menu:query") @GetMapping(value = "/{menuId}") public AjaxResult getInfo(@PathVariable Long menuId) { return AjaxResult.success(menuService.selectMenuById(menuId)); @@ -53,7 +53,7 @@ public class SysMenuController extends BaseController { */ @GetMapping("/treeselect") public AjaxResult treeselect(SysMenu menu) { - Long userId = SecurityUtils.getUserId(); + Long userId = LoginHelper.getUserId(); List menus = menuService.selectMenuList(menu, userId); return AjaxResult.success(menuService.buildMenuTreeSelect(menus)); } @@ -63,7 +63,7 @@ public class SysMenuController extends BaseController { */ @GetMapping(value = "/roleMenuTreeselect/{roleId}") public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) { - Long userId = SecurityUtils.getUserId(); + Long userId = LoginHelper.getUserId(); List menus = menuService.selectMenuList(userId); AjaxResult ajax = AjaxResult.success(); ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); @@ -74,7 +74,7 @@ public class SysMenuController extends BaseController { /** * 新增菜单 */ - @RequiresPermissions("system:menu:add") + @SaCheckPermission("system:menu:add") @Log(title = "菜单管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysMenu menu) { @@ -83,14 +83,14 @@ public class SysMenuController extends BaseController { } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); } - menu.setCreateBy(SecurityUtils.getUsername()); + menu.setCreateBy(LoginHelper.getUsername()); return toAjax(menuService.insertMenu(menu)); } /** * 修改菜单 */ - @RequiresPermissions("system:menu:edit") + @SaCheckPermission("system:menu:edit") @Log(title = "菜单管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysMenu menu) { @@ -101,14 +101,14 @@ public class SysMenuController extends BaseController { } else if (menu.getMenuId().equals(menu.getParentId())) { return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); } - menu.setUpdateBy(SecurityUtils.getUsername()); + menu.setUpdateBy(LoginHelper.getUsername()); return toAjax(menuService.updateMenu(menu)); } /** * 删除菜单 */ - @RequiresPermissions("system:menu:remove") + @SaCheckPermission("system:menu:remove") @Log(title = "菜单管理", businessType = BusinessType.DELETE) @DeleteMapping("/{menuId}") public AjaxResult remove(@PathVariable("menuId") Long menuId) { @@ -128,7 +128,7 @@ public class SysMenuController extends BaseController { */ @GetMapping("getRouters") public AjaxResult getRouters() { - Long userId = SecurityUtils.getUserId(); + Long userId = LoginHelper.getUserId(); List menus = menuService.selectMenuTreeByUserId(userId); return AjaxResult.success(menuService.buildMenus(menus)); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java index 6178b55ee..7f7f65453 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java @@ -1,13 +1,13 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.domain.SysNotice; import com.ruoyi.system.service.ISysNoticeService; import lombok.RequiredArgsConstructor; @@ -29,7 +29,7 @@ public class SysNoticeController extends BaseController { /** * 获取通知公告列表 */ - @RequiresPermissions("system:notice:list") + @SaCheckPermission("system:notice:list") @GetMapping("/list") public TableDataInfo list(SysNotice notice, PageQuery pageQuery) { return noticeService.selectPageNoticeList(notice, pageQuery); @@ -38,7 +38,7 @@ public class SysNoticeController extends BaseController { /** * 根据通知公告编号获取详细信息 */ - @RequiresPermissions("system:notice:query") + @SaCheckPermission("system:notice:query") @GetMapping(value = "/{noticeId}") public AjaxResult getInfo(@PathVariable Long noticeId) { return AjaxResult.success(noticeService.selectNoticeById(noticeId)); @@ -47,29 +47,29 @@ public class SysNoticeController extends BaseController { /** * 新增通知公告 */ - @RequiresPermissions("system:notice:add") + @SaCheckPermission("system:notice:add") @Log(title = "通知公告", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysNotice notice) { - notice.setCreateBy(SecurityUtils.getUsername()); + notice.setCreateBy(LoginHelper.getUsername()); return toAjax(noticeService.insertNotice(notice)); } /** * 修改通知公告 */ - @RequiresPermissions("system:notice:edit") + @SaCheckPermission("system:notice:edit") @Log(title = "通知公告", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysNotice notice) { - notice.setUpdateBy(SecurityUtils.getUsername()); + notice.setUpdateBy(LoginHelper.getUsername()); return toAjax(noticeService.updateNotice(notice)); } /** * 删除通知公告 */ - @RequiresPermissions("system:notice:remove") + @SaCheckPermission("system:notice:remove") @Log(title = "通知公告", businessType = BusinessType.DELETE) @DeleteMapping("/{noticeIds}") public AjaxResult remove(@PathVariable Long[] noticeIds) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysOperlogController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysOperlogController.java index e1a3daff9..4c62a00b8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysOperlogController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysOperlogController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.excel.utils.ExcelUtil; @@ -7,8 +8,6 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.InnerAuth; -import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.system.api.domain.SysOperLog; import com.ruoyi.system.service.ISysOperLogService; import lombok.RequiredArgsConstructor; @@ -28,14 +27,14 @@ import java.util.List; public class SysOperlogController extends BaseController { private final ISysOperLogService operLogService; - @RequiresPermissions("system:operlog:list") + @SaCheckPermission("system:operlog:list") @GetMapping("/list") public TableDataInfo list(SysOperLog operLog, PageQuery pageQuery) { return operLogService.selectPageOperLogList(operLog, pageQuery); } @Log(title = "操作日志", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:operlog:export") + @SaCheckPermission("system:operlog:export") @PostMapping("/export") public void export(HttpServletResponse response, SysOperLog operLog) { List list = operLogService.selectOperLogList(operLog); @@ -43,13 +42,13 @@ public class SysOperlogController extends BaseController { } @Log(title = "操作日志", businessType = BusinessType.DELETE) - @RequiresPermissions("system:operlog:remove") + @SaCheckPermission("system:operlog:remove") @DeleteMapping("/{operIds}") public AjaxResult remove(@PathVariable Long[] operIds) { return toAjax(operLogService.deleteOperLogByIds(operIds)); } - @RequiresPermissions("system:operlog:remove") + @SaCheckPermission("system:operlog:remove") @Log(title = "操作日志", businessType = BusinessType.CLEAN) @DeleteMapping("/clean") public AjaxResult clean() { @@ -57,7 +56,7 @@ public class SysOperlogController extends BaseController { return AjaxResult.success(); } - @InnerAuth +// @InnerAuth @PostMapping public AjaxResult add(@RequestBody SysOperLog operLog) { return toAjax(operLogService.insertOperlog(operLog)); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java index 89dbf4cc4..f7706e5a5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; @@ -8,8 +9,7 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.domain.SysPost; import com.ruoyi.system.service.ISysPostService; import lombok.RequiredArgsConstructor; @@ -34,14 +34,14 @@ public class SysPostController extends BaseController { /** * 获取岗位列表 */ - @RequiresPermissions("system:post:list") + @SaCheckPermission("system:post:list") @GetMapping("/list") public TableDataInfo list(SysPost post, PageQuery pageQuery) { return postService.selectPagePostList(post, pageQuery); } @Log(title = "岗位管理", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:post:export") + @SaCheckPermission("system:post:export") @PostMapping("/export") public void export(HttpServletResponse response, SysPost post) { List list = postService.selectPostList(post); @@ -51,7 +51,7 @@ public class SysPostController extends BaseController { /** * 根据岗位编号获取详细信息 */ - @RequiresPermissions("system:post:query") + @SaCheckPermission("system:post:query") @GetMapping(value = "/{postId}") public AjaxResult getInfo(@PathVariable Long postId) { return AjaxResult.success(postService.selectPostById(postId)); @@ -60,7 +60,7 @@ public class SysPostController extends BaseController { /** * 新增岗位 */ - @RequiresPermissions("system:post:add") + @SaCheckPermission("system:post:add") @Log(title = "岗位管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysPost post) { @@ -69,14 +69,14 @@ public class SysPostController extends BaseController { } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) { return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); } - post.setCreateBy(SecurityUtils.getUsername()); + post.setCreateBy(LoginHelper.getUsername()); return toAjax(postService.insertPost(post)); } /** * 修改岗位 */ - @RequiresPermissions("system:post:edit") + @SaCheckPermission("system:post:edit") @Log(title = "岗位管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysPost post) { @@ -85,14 +85,14 @@ public class SysPostController extends BaseController { } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) { return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); } - post.setUpdateBy(SecurityUtils.getUsername()); + post.setUpdateBy(LoginHelper.getUsername()); return toAjax(postService.updatePost(post)); } /** * 删除岗位 */ - @RequiresPermissions("system:post:remove") + @SaCheckPermission("system:post:remove") @Log(title = "岗位管理", businessType = BusinessType.DELETE) @DeleteMapping("/{postIds}") public AjaxResult remove(@PathVariable Long[] postIds) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java index 3bba38c27..21b5ce1bb 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java @@ -7,12 +7,11 @@ import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; -import com.ruoyi.common.security.service.TokenService; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.file.api.RemoteFileService; import com.ruoyi.file.api.domain.SysFile; import com.ruoyi.system.api.domain.SysUser; -import com.ruoyi.system.api.model.LoginUser; import com.ruoyi.system.service.ISysUserService; import lombok.RequiredArgsConstructor; import org.apache.dubbo.config.annotation.DubboReference; @@ -32,7 +31,6 @@ import java.io.IOException; public class SysProfileController extends BaseController { private final ISysUserService userService; - private final TokenService tokenService; @DubboReference private RemoteFileService remoteFileService; @@ -42,7 +40,7 @@ public class SysProfileController extends BaseController { */ @GetMapping public AjaxResult profile() { - String username = SecurityUtils.getUsername(); + String username = LoginHelper.getUsername(); SysUser user = userService.selectUserByUserName(username); AjaxResult ajax = AjaxResult.success(user); ajax.put("roleGroup", userService.selectUserRoleGroup(username)); @@ -56,9 +54,6 @@ public class SysProfileController extends BaseController { @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult updateProfile(@RequestBody SysUser user) { - LoginUser loginUser = SecurityUtils.getLoginUser(); - SysUser sysUser = loginUser.getSysUser(); - user.setUserName(sysUser.getUserName()); if (StringUtils.isNotEmpty(user.getPhonenumber()) && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); @@ -66,15 +61,16 @@ public class SysProfileController extends BaseController { && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } - user.setUserId(sysUser.getUserId()); + user.setUserId(LoginHelper.getUserId()); + user.setUserName(null); user.setPassword(null); if (userService.updateUserProfile(user) > 0) { // 更新缓存用户信息 - loginUser.getSysUser().setNickName(user.getNickName()); - loginUser.getSysUser().setPhonenumber(user.getPhonenumber()); - loginUser.getSysUser().setEmail(user.getEmail()); - loginUser.getSysUser().setSex(user.getSex()); - tokenService.setLoginUser(loginUser); +// loginUser.getSysUser().setNickName(user.getNickName()); +// loginUser.getSysUser().setPhonenumber(user.getPhonenumber()); +// loginUser.getSysUser().setEmail(user.getEmail()); +// loginUser.getSysUser().setSex(user.getSex()); +// tokenService.setLoginUser(loginUser); return AjaxResult.success(); } return AjaxResult.error("修改个人信息异常,请联系管理员"); @@ -86,8 +82,7 @@ public class SysProfileController extends BaseController { @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping("/updatePwd") public AjaxResult updatePwd(String oldPassword, String newPassword) { - String username = SecurityUtils.getUsername(); - SysUser user = userService.selectUserByUserName(username); + SysUser user = userService.selectUserById(LoginHelper.getUserId()); String password = user.getPassword(); if (!SecurityUtils.matchesPassword(oldPassword, password)) { return AjaxResult.error("修改密码失败,旧密码错误"); @@ -95,12 +90,12 @@ public class SysProfileController extends BaseController { if (SecurityUtils.matchesPassword(newPassword, password)) { return AjaxResult.error("新密码不能与旧密码相同"); } - if (userService.resetUserPwd(username, SecurityUtils.encryptPassword(newPassword)) > 0) { + if (userService.resetUserPwd(user.getUserName(), SecurityUtils.encryptPassword(newPassword)) > 0) { // 更新缓存用户密码 - LoginUser loginUser = SecurityUtils.getLoginUser(); - loginUser.getSysUser().setPassword(SecurityUtils.encryptPassword(newPassword)); - tokenService.setLoginUser(loginUser); - return AjaxResult.success(); +// LoginUser loginUser = LoginHelper.getLoginUser(); +// loginUser.getSysUser().setPassword(SecurityUtils.encryptPassword(newPassword)); +// tokenService.setLoginUser(loginUser); +// return AjaxResult.success(); } return AjaxResult.error("修改密码异常,请联系管理员"); } @@ -116,18 +111,17 @@ public class SysProfileController extends BaseController { // userService.insertUser(new SysUser().setUserName("test").setNickName("test")); if (!file.isEmpty()) { - LoginUser loginUser = SecurityUtils.getLoginUser(); SysFile sysFile = remoteFileService.upload(file.getName(), file.getOriginalFilename(), file.getContentType(), file.getBytes()); if (ObjectUtil.isNull(sysFile)) { return AjaxResult.error("文件服务异常,请联系管理员"); } String url = sysFile.getUrl(); - if (userService.updateUserAvatar(loginUser.getUsername(), url)) { + if (userService.updateUserAvatar(LoginHelper.getUsername(), url)) { AjaxResult ajax = AjaxResult.success(); ajax.put("imgUrl", url); // 更新缓存用户头像 - loginUser.getSysUser().setAvatar(url); - tokenService.setLoginUser(loginUser); +// loginUser.getSysUser().setAvatar(url); +// tokenService.setLoginUser(loginUser); return ajax; } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java index 01726f0db..cba0bfac7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; @@ -8,8 +9,7 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.domain.SysUserRole; @@ -35,14 +35,14 @@ public class SysRoleController extends BaseController { private final ISysRoleService roleService; private final ISysUserService userService; - @RequiresPermissions("system:role:list") + @SaCheckPermission("system:role:list") @GetMapping("/list") public TableDataInfo list(SysRole role, PageQuery pageQuery) { return roleService.selectPageRoleList(role, pageQuery); } @Log(title = "角色管理", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:role:export") + @SaCheckPermission("system:role:export") @PostMapping("/export") public void export(HttpServletResponse response, SysRole role) { List list = roleService.selectRoleList(role); @@ -52,7 +52,7 @@ public class SysRoleController extends BaseController { /** * 根据角色编号获取详细信息 */ - @RequiresPermissions("system:role:query") + @SaCheckPermission("system:role:query") @GetMapping(value = "/{roleId}") public AjaxResult getInfo(@PathVariable Long roleId) { roleService.checkRoleDataScope(roleId); @@ -62,7 +62,7 @@ public class SysRoleController extends BaseController { /** * 新增角色 */ - @RequiresPermissions("system:role:add") + @SaCheckPermission("system:role:add") @Log(title = "角色管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysRole role) { @@ -71,7 +71,7 @@ public class SysRoleController extends BaseController { } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); } - role.setCreateBy(SecurityUtils.getUsername()); + role.setCreateBy(LoginHelper.getUsername()); return toAjax(roleService.insertRole(role)); } @@ -79,7 +79,7 @@ public class SysRoleController extends BaseController { /** * 修改保存角色 */ - @RequiresPermissions("system:role:edit") + @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysRole role) { @@ -89,14 +89,14 @@ public class SysRoleController extends BaseController { } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); } - role.setUpdateBy(SecurityUtils.getUsername()); + role.setUpdateBy(LoginHelper.getUsername()); return toAjax(roleService.updateRole(role)); } /** * 修改保存数据权限 */ - @RequiresPermissions("system:role:edit") + @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.UPDATE) @PutMapping("/dataScope") public AjaxResult dataScope(@RequestBody SysRole role) { @@ -107,19 +107,19 @@ public class SysRoleController extends BaseController { /** * 状态修改 */ - @RequiresPermissions("system:role:edit") + @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") public AjaxResult changeStatus(@RequestBody SysRole role) { roleService.checkRoleAllowed(role); - role.setUpdateBy(SecurityUtils.getUsername()); + role.setUpdateBy(LoginHelper.getUsername()); return toAjax(roleService.updateRoleStatus(role)); } /** * 删除角色 */ - @RequiresPermissions("system:role:remove") + @SaCheckPermission("system:role:remove") @Log(title = "角色管理", businessType = BusinessType.DELETE) @DeleteMapping("/{roleIds}") public AjaxResult remove(@PathVariable Long[] roleIds) { @@ -129,7 +129,7 @@ public class SysRoleController extends BaseController { /** * 获取角色选择框列表 */ - @RequiresPermissions("system:role:query") + @SaCheckPermission("system:role:query") @GetMapping("/optionselect") public AjaxResult optionselect() { return AjaxResult.success(roleService.selectRoleAll()); @@ -138,7 +138,7 @@ public class SysRoleController extends BaseController { /** * 查询已分配用户角色列表 */ - @RequiresPermissions("system:role:list") + @SaCheckPermission("system:role:list") @GetMapping("/authUser/allocatedList") public TableDataInfo allocatedList(SysUser user, PageQuery pageQuery) { return userService.selectAllocatedList(user, pageQuery); @@ -147,7 +147,7 @@ public class SysRoleController extends BaseController { /** * 查询未分配用户角色列表 */ - @RequiresPermissions("system:role:list") + @SaCheckPermission("system:role:list") @GetMapping("/authUser/unallocatedList") public TableDataInfo unallocatedList(SysUser user, PageQuery pageQuery) { return userService.selectUnallocatedList(user, pageQuery); @@ -156,7 +156,7 @@ public class SysRoleController extends BaseController { /** * 取消授权用户 */ - @RequiresPermissions("system:role:edit") + @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.GRANT) @PutMapping("/authUser/cancel") public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole) { @@ -166,7 +166,7 @@ public class SysRoleController extends BaseController { /** * 批量取消授权用户 */ - @RequiresPermissions("system:role:edit") + @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.GRANT) @PutMapping("/authUser/cancelAll") public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) { @@ -176,7 +176,7 @@ public class SysRoleController extends BaseController { /** * 批量选择用户授权 */ - @RequiresPermissions("system:role:edit") + @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.GRANT) @PutMapping("/authUser/selectAll") public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java index 426767a42..2891eedb4 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java @@ -1,5 +1,6 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.core.constant.UserConstants; @@ -12,7 +13,7 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysRole; @@ -55,14 +56,14 @@ public class SysUserController extends BaseController { /** * 获取用户列表 */ - @RequiresPermissions("system:user:list") + @SaCheckPermission("system:user:list") @GetMapping("/list") public TableDataInfo list(SysUser user, PageQuery pageQuery) { return userService.selectPageUserList(user, pageQuery); } @Log(title = "用户管理", businessType = BusinessType.EXPORT) - @RequiresPermissions("system:user:export") + @SaCheckPermission("system:user:export") @PostMapping("/export") public void export(HttpServletResponse response, SysUser user) { List list = userService.selectUserList(user); @@ -79,7 +80,7 @@ public class SysUserController extends BaseController { } @Log(title = "用户管理", businessType = BusinessType.IMPORT) - @RequiresPermissions("system:user:import") + @SaCheckPermission("system:user:import") @PostMapping("/importData") public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception { ExcelResult result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport)); @@ -98,7 +99,8 @@ public class SysUserController extends BaseController { */ @GetMapping("getInfo") public AjaxResult getInfo() { - Long userId = SecurityUtils.getUserId(); + //Long userId = SecurityUtils.getUserId(); + Long userId = LoginHelper.getUserId(); // 角色集合 Set roles = permissionService.getRolePermission(userId); // 权限集合 @@ -113,7 +115,7 @@ public class SysUserController extends BaseController { /** * 根据用户编号获取详细信息 */ - @RequiresPermissions("system:user:query") + @SaCheckPermission("system:user:query") @GetMapping(value = {"/", "/{userId}"}) public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) { userService.checkUserDataScope(userId); @@ -133,7 +135,7 @@ public class SysUserController extends BaseController { /** * 新增用户 */ - @RequiresPermissions("system:user:add") + @SaCheckPermission("system:user:add") @Log(title = "用户管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysUser user) { @@ -146,7 +148,7 @@ public class SysUserController extends BaseController { && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } - user.setCreateBy(SecurityUtils.getUsername()); + user.setCreateBy(LoginHelper.getUsername()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); return toAjax(userService.insertUser(user)); } @@ -154,7 +156,7 @@ public class SysUserController extends BaseController { /** * 修改用户 */ - @RequiresPermissions("system:user:edit") + @SaCheckPermission("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysUser user) { @@ -166,18 +168,18 @@ public class SysUserController extends BaseController { && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } - user.setUpdateBy(SecurityUtils.getUsername()); + user.setUpdateBy(LoginHelper.getUsername()); return toAjax(userService.updateUser(user)); } /** * 删除用户 */ - @RequiresPermissions("system:user:remove") + @SaCheckPermission("system:user:remove") @Log(title = "用户管理", businessType = BusinessType.DELETE) @DeleteMapping("/{userIds}") public AjaxResult remove(@PathVariable Long[] userIds) { - if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) { + if (ArrayUtils.contains(userIds, LoginHelper.getUserId())) { return AjaxResult.error("当前用户不能删除"); } return toAjax(userService.deleteUserByIds(userIds)); @@ -186,32 +188,32 @@ public class SysUserController extends BaseController { /** * 重置密码 */ - @RequiresPermissions("system:user:edit") + @SaCheckPermission("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/resetPwd") public AjaxResult resetPwd(@RequestBody SysUser user) { userService.checkUserAllowed(user); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); - user.setUpdateBy(SecurityUtils.getUsername()); + user.setUpdateBy(LoginHelper.getUsername()); return toAjax(userService.resetPwd(user)); } /** * 状态修改 */ - @RequiresPermissions("system:user:edit") + @SaCheckPermission("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") public AjaxResult changeStatus(@RequestBody SysUser user) { userService.checkUserAllowed(user); - user.setUpdateBy(SecurityUtils.getUsername()); + user.setUpdateBy(LoginHelper.getUsername()); return toAjax(userService.updateUserStatus(user)); } /** * 根据用户编号获取授权角色 */ - @RequiresPermissions("system:user:query") + @SaCheckPermission("system:user:query") @GetMapping("/authRole/{userId}") public AjaxResult authRole(@PathVariable("userId") Long userId) { AjaxResult ajax = AjaxResult.success(); @@ -225,7 +227,7 @@ public class SysUserController extends BaseController { /** * 用户授权角色 */ - @RequiresPermissions("system:user:edit") + @SaCheckPermission("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.GRANT) @PutMapping("/authRole") public AjaxResult insertAuthRole(Long userId, Long[] roleIds) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserOnlineController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserOnlineController.java index da0200f07..4cd12d605 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserOnlineController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserOnlineController.java @@ -1,5 +1,8 @@ package com.ruoyi.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.web.controller.BaseController; @@ -8,17 +11,15 @@ import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.mybatis.core.page.TableDataInfo; import com.ruoyi.common.redis.utils.RedisUtils; -import com.ruoyi.common.security.annotation.RequiresPermissions; -import com.ruoyi.system.api.model.LoginUser; -import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.api.domain.SysUserOnline; import com.ruoyi.system.service.ISysUserOnlineService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; /** * 在线用户监控 @@ -32,28 +33,33 @@ public class SysUserOnlineController extends BaseController { private final ISysUserOnlineService userOnlineService; - @RequiresPermissions("monitor:online:list") + @SaCheckPermission("monitor:online:list") @GetMapping("/list") public TableDataInfo list(String ipaddr, String userName) { - Collection keys = RedisUtils.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + // 获取所有未过期的 token + List keys = StpUtil.searchTokenValue("", -1, 0); List userOnlineList = new ArrayList(); for (String key : keys) { - LoginUser user = RedisUtils.getCacheObject(key); - if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) { - if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) { - userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); - } - } else if (StringUtils.isNotEmpty(ipaddr)) { - if (StringUtils.equals(ipaddr, user.getIpaddr())) { - userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); - } - } else if (StringUtils.isNotEmpty(userName)) { - if (StringUtils.equals(userName, user.getUsername())) { - userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); - } - } else { - userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); + String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, ""); + // 如果已经过期则踢下线 + if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < 0) { + continue; } + userOnlineList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token)); + } + if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) { + userOnlineList = userOnlineList.stream().filter(userOnline -> + StringUtils.equals(ipaddr, userOnline.getIpaddr()) && + StringUtils.equals(userName, userOnline.getUserName()) + ).collect(Collectors.toList()); + } else if (StringUtils.isNotEmpty(ipaddr)) { + userOnlineList = userOnlineList.stream().filter(userOnline -> + StringUtils.equals(ipaddr, userOnline.getIpaddr())) + .collect(Collectors.toList()); + } else if (StringUtils.isNotEmpty(userName)) { + userOnlineList = userOnlineList.stream().filter(userOnline -> + StringUtils.equals(userName, userOnline.getUserName()) + ).collect(Collectors.toList()); } Collections.reverse(userOnlineList); userOnlineList.removeAll(Collections.singleton(null)); @@ -63,11 +69,15 @@ public class SysUserOnlineController extends BaseController { /** * 强退用户 */ - @RequiresPermissions("monitor:online:forceLogout") + @SaCheckPermission("monitor:online:forceLogout") @Log(title = "在线用户", businessType = BusinessType.FORCE) @DeleteMapping("/{tokenId}") public AjaxResult forceLogout(@PathVariable String tokenId) { - RedisUtils.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); + try { + StpUtil.kickoutByTokenValue(tokenId); + } catch (NotLoginException e) { + } + //RedisUtils.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); return AjaxResult.success(); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteDataScopeServiceImpl.java new file mode 100644 index 000000000..a936c7c32 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteDataScopeServiceImpl.java @@ -0,0 +1,56 @@ +package com.ruoyi.system.dubbo; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.system.api.RemoteDataScopeService; +import com.ruoyi.system.api.domain.SysDept; +import com.ruoyi.system.domain.SysRoleDept; +import com.ruoyi.system.mapper.SysDeptMapper; +import com.ruoyi.system.mapper.SysRoleDeptMapper; +import lombok.RequiredArgsConstructor; +import org.apache.dubbo.config.annotation.DubboService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据权限 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +@DubboService +public class RemoteDataScopeServiceImpl implements RemoteDataScopeService { + + private final SysRoleDeptMapper roleDeptMapper; + private final SysDeptMapper deptMapper; + + @Override + public String getRoleCustom(Long roleId) { + List list = roleDeptMapper.selectList( + new LambdaQueryWrapper() + .select(SysRoleDept::getDeptId) + .eq(SysRoleDept::getRoleId, roleId)); + if (CollUtil.isNotEmpty(list)) { + return list.stream().map(rd -> Convert.toStr(rd.getDeptId())).collect(Collectors.joining(",")); + } + return null; + } + + @Override + public String getDeptAndChild(Long deptId) { + List list = deptMapper.selectList(new LambdaQueryWrapper() + .select(SysDept::getDeptId) + .eq(SysDept::getDeptId, deptId) + .or() + .apply("find_in_set({0},ancestors)", deptId)); + if (CollUtil.isNotEmpty(list)) { + return list.stream().map(d -> Convert.toStr(d.getDeptId())).collect(Collectors.joining(",")); + } + return null; + } + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java index ed5d91f93..05bd0484b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java @@ -1,11 +1,15 @@ package com.ruoyi.system.dubbo; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; +import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.UserConstants; +import com.ruoyi.common.core.enums.UserStatus; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.system.api.RemoteUserService; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.model.LoginUser; +import com.ruoyi.system.api.model.RoleDTO; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysPermissionService; import com.ruoyi.system.service.ISysUserService; @@ -13,6 +17,7 @@ import lombok.RequiredArgsConstructor; import org.apache.dubbo.config.annotation.DubboService; import org.springframework.stereotype.Service; +import java.util.List; import java.util.Set; /** @@ -35,15 +40,28 @@ public class RemoteUserServiceImpl implements RemoteUserService { if (ObjectUtil.isNull(sysUser)) { throw new ServiceException("用户名或密码错误"); } + if (UserStatus.DELETED.getCode().equals(sysUser.getDelFlag())) { + throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + } + if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus())) { + throw new ServiceException("对不起,您的账号:" + username + " 已停用"); + } // 角色集合 - Set roles = permissionService.getRolePermission(sysUser.getUserId()); + Set rolePermission = permissionService.getRolePermission(sysUser.getUserId()); // 权限集合 - Set permissions = permissionService.getMenuPermission(sysUser.getUserId()); - LoginUser sysUserVo = new LoginUser(); - sysUserVo.setSysUser(sysUser); - sysUserVo.setRoles(roles); - sysUserVo.setPermissions(permissions); - return sysUserVo; + Set menuPermissions = permissionService.getMenuPermission(sysUser.getUserId()); + LoginUser loginUser = new LoginUser(); + loginUser.setUserId(sysUser.getUserId()); + loginUser.setDeptId(sysUser.getDeptId()); + loginUser.setUsername(sysUser.getUserName()); + loginUser.setPassword(sysUser.getPassword()); + loginUser.setUserType(sysUser.getUserType()); + loginUser.setDeptName(sysUser.getDept().getDeptName()); + loginUser.setMenuPermission(menuPermissions); + loginUser.setRolePermission(rolePermission); + List roles = BeanUtil.copyToList(sysUser.getRoles(), RoleDTO.class); + loginUser.setRoles(roles); + return loginUser; } @Override diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java index 2de97e445..81fe5c6b5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java @@ -9,6 +9,7 @@ import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.core.utils.ValidatorUtils; import com.ruoyi.common.excel.core.ExcelListener; import com.ruoyi.common.excel.core.ExcelResult; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.domain.vo.SysUserImportVo; @@ -44,7 +45,7 @@ public class SysUserImportListener extends AnalysisEventListener depts = SpringUtils.getAopProxy(this).selectDeptList(dept); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java index 391376335..9db1fcb49 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -9,7 +9,7 @@ import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.domain.SysRoleDept; @@ -181,7 +181,7 @@ public class SysRoleServiceImpl implements ISysRoleService { */ @Override public void checkRoleDataScope(Long roleId) { - if (!SysUser.isAdmin(SecurityUtils.getUserId())) { + if (!SysUser.isAdmin(LoginHelper.getUserId())) { SysRole role = new SysRole(); role.setRoleId(roleId); List roles = SpringUtils.getAopProxy(this).selectRoleList(role); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java index 49273c5e5..0bf7102ff 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java @@ -3,7 +3,7 @@ package com.ruoyi.system.service.impl; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.system.api.model.LoginUser; -import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.api.domain.SysUserOnline; import com.ruoyi.system.service.ISysUserOnlineService; import org.springframework.stereotype.Service; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index b9bd7dd4f..54a2bc1a0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -11,7 +11,7 @@ import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; -import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.domain.SysPost; @@ -207,7 +207,7 @@ public class SysUserServiceImpl implements ISysUserService { */ @Override public void checkUserDataScope(Long userId) { - if (!SysUser.isAdmin(SecurityUtils.getUserId())) { + if (!SysUser.isAdmin(LoginHelper.getUserId())) { SysUser user = new SysUser(); user.setUserId(userId); List users = SpringUtils.getAopProxy(this).selectUserList(user); diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml index 8daaf7207..c6d2c1a6f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -9,6 +9,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + diff --git a/ruoyi-ui/src/api/login.js b/ruoyi-ui/src/api/login.js index 6b0cda03d..b7506e473 100644 --- a/ruoyi-ui/src/api/login.js +++ b/ruoyi-ui/src/api/login.js @@ -1,61 +1,49 @@ -import request from '@/utils/request' - -// 登录方法 -export function login(username, password, code, uuid) { - return request({ - url: '/auth/login', - headers: { - isToken: false - }, - method: 'post', - data: { username, password, code, uuid } - }) -} - -// 注册方法 -export function register(data) { - return request({ - url: '/auth/register', - headers: { - isToken: false - }, - method: 'post', - data: data - }) -} - -// 刷新方法 -export function refreshToken() { - return request({ - url: '/auth/refresh', - method: 'post' - }) -} - -// 获取用户详细信息 -export function getInfo() { - return request({ - url: '/system/user/getInfo', - method: 'get' - }) -} - -// 退出方法 -export function logout() { - return request({ - url: '/auth/logout', - method: 'delete' - }) -} - -// 获取验证码 -export function getCodeImg() { - return request({ - url: '/code', - headers: { - isToken: false - }, - method: 'get', - timeout: 20000 - }) -} \ No newline at end of file +import request from '@/utils/request' + +// 登录方法 +export function login(username, password, code, uuid) { + return request({ + url: '/auth/login', + headers: { + isToken: false + }, + method: 'post', + data: { username, password, code, uuid } + }) +} + +// 刷新方法 +export function refreshToken() { + return request({ + url: '/auth/refresh', + method: 'post' + }) +} + +// 获取用户详细信息 +export function getInfo() { + return request({ + url: '/system/user/getInfo', + method: 'get' + }) +} + +// 退出方法 +export function logout() { + return request({ + url: '/auth/logout', + method: 'delete' + }) +} + +// 获取验证码 +export function getCodeImg() { + return request({ + url: '/code', + headers: { + isToken: false + }, + method: 'get', + timeout: 20000 + }) +} diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 103706da9..6c0bac669 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -1,115 +1,102 @@ -import { login, logout, getInfo, refreshToken } from '@/api/login' -import { getToken, setToken, setExpiresIn, removeToken } from '@/utils/auth' - -const user = { - state: { - token: getToken(), - name: '', - avatar: '', - roles: [], - permissions: [] - }, - - mutations: { - SET_TOKEN: (state, token) => { - state.token = token - }, - SET_EXPIRES_IN: (state, time) => { - state.expires_in = time - }, - SET_NAME: (state, name) => { - state.name = name - }, - SET_AVATAR: (state, avatar) => { - state.avatar = avatar - }, - SET_ROLES: (state, roles) => { - state.roles = roles - }, - SET_PERMISSIONS: (state, permissions) => { - state.permissions = permissions - } - }, - - actions: { - // 登录 - Login({ commit }, userInfo) { - const username = userInfo.username.trim() - const password = userInfo.password - const code = userInfo.code - const uuid = userInfo.uuid - return new Promise((resolve, reject) => { - login(username, password, code, uuid).then(res => { - let data = res.data - setToken(data.access_token) - commit('SET_TOKEN', data.access_token) - setExpiresIn(data.expires_in) - commit('SET_EXPIRES_IN', data.expires_in) - resolve() - }).catch(error => { - reject(error) - }) - }) - }, - - // 获取用户信息 - GetInfo({ commit, state }) { - return new Promise((resolve, reject) => { - getInfo().then(res => { - const user = res.user - const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : user.avatar; - if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 - commit('SET_ROLES', res.roles) - commit('SET_PERMISSIONS', res.permissions) - } else { - commit('SET_ROLES', ['ROLE_DEFAULT']) - } - commit('SET_NAME', user.userName) - commit('SET_AVATAR', avatar) - resolve(res) - }).catch(error => { - reject(error) - }) - }) - }, - - // 刷新token - RefreshToken({commit, state}) { - return new Promise((resolve, reject) => { - refreshToken(state.token).then(res => { - setExpiresIn(res.data) - commit('SET_EXPIRES_IN', res.data) - resolve() - }).catch(error => { - reject(error) - }) - }) - }, - - // 退出系统 - LogOut({ commit, state }) { - return new Promise((resolve, reject) => { - logout(state.token).then(() => { - commit('SET_TOKEN', '') - commit('SET_ROLES', []) - commit('SET_PERMISSIONS', []) - removeToken() - resolve() - }).catch(error => { - reject(error) - }) - }) - }, - - // 前端 登出 - FedLogOut({ commit }) { - return new Promise(resolve => { - commit('SET_TOKEN', '') - removeToken() - resolve() - }) - } - } -} - -export default user +import { login, logout, getInfo, refreshToken } from '@/api/login' +import { getToken, setToken, setExpiresIn, removeToken } from '@/utils/auth' + +const user = { + state: { + token: getToken(), + name: '', + avatar: '', + roles: [], + permissions: [] + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_EXPIRES_IN: (state, time) => { + state.expires_in = time + }, + SET_NAME: (state, name) => { + state.name = name + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + }, + SET_ROLES: (state, roles) => { + state.roles = roles + }, + SET_PERMISSIONS: (state, permissions) => { + state.permissions = permissions + } + }, + + actions: { + // 登录 + Login({ commit }, userInfo) { + const username = userInfo.username.trim() + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(username, password, code, uuid).then(res => { + let data = res.data + setToken(data.access_token) + commit('SET_TOKEN', data.access_token) + setExpiresIn(data.expires_in) + commit('SET_EXPIRES_IN', data.expires_in) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.user + const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : user.avatar; + if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 + commit('SET_ROLES', res.roles) + commit('SET_PERMISSIONS', res.permissions) + } else { + commit('SET_ROLES', ['ROLE_DEFAULT']) + } + commit('SET_NAME', user.userName) + commit('SET_AVATAR', avatar) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 退出系统 + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + commit('SET_PERMISSIONS', []) + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 前端 登出 + FedLogOut({ commit }) { + return new Promise(resolve => { + commit('SET_TOKEN', '') + removeToken() + resolve() + }) + } + } +} + +export default user diff --git a/sql/ry-cloud.sql b/sql/ry-cloud.sql index 1e619cf41..de7ee0a9b 100644 --- a/sql/ry-cloud.sql +++ b/sql/ry-cloud.sql @@ -46,7 +46,7 @@ create table sys_user ( dept_id bigint(20) default null comment '部门ID', user_name varchar(30) not null comment '用户账号', nick_name varchar(30) not null comment '用户昵称', - user_type varchar(2) default '00' comment '用户类型(00系统用户)', + user_type varchar(10) default 'sys_user' comment '用户类型(sys_user系统用户)', email varchar(50) default '' comment '用户邮箱', phonenumber varchar(11) default '' comment '手机号码', sex char(1) default '0' comment '用户性别(0男 1女 2未知)', @@ -67,8 +67,8 @@ create table sys_user ( -- ---------------------------- -- 初始化-用户信息表数据 -- ---------------------------- -insert into sys_user values(1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '管理员'); -insert into sys_user values(2, 105, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '测试员'); +insert into sys_user values(1, 103, 'admin', '若依', 'sys_user', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '管理员'); +insert into sys_user values(2, 105, 'ry', '若依', 'sys_user', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '测试员'); -- ----------------------------