!15 合并 新功能/satoken 分支

This commit is contained in:
疯狂的狮子Li
2022-01-28 11:35:54 +00:00
parent fe7b636ef8
commit db70abf9f0
93 changed files with 1799 additions and 2192 deletions

View File

@@ -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:

View File

@@ -20,6 +20,7 @@ security:
# 不校验白名单
ignore:
whites:
- /code
- /auth/logout
- /auth/login
- /auth/register

View File

@@ -47,6 +47,7 @@
<xxl-job.version>2.3.0</xxl-job.version>
<knife4j-aggregation.version>2.0.9</knife4j-aggregation.version>
<knife4j.version>3.0.3</knife4j.version>
<satoken.version>1.28.0</satoken.version>
<!-- docker 配置 -->
<docker.registry.url>localhost</docker.registry.url>
@@ -273,13 +274,6 @@
<version>${commons-collections.version}</version>
</dependency>
<!-- 线程传递值 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${transmittable-thread-local.version}</version>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>

View File

@@ -0,0 +1,20 @@
package com.ruoyi.system.api;
/**
* 数据权限服务
*
* @author Lion Li
*/
public interface RemoteDataScopeService {
/**
* 获取角色自定义权限语句
*/
String getRoleCustom(Long roleId);
/**
* 获取部门和下级权限语句
*/
String getDeptAndChild(Long deptId);
}

View File

@@ -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 {
/**
* 会话编号

View File

@@ -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<String> permissions;
private String loginLocation;
/**
* 角色列表
* 浏览器类型
*/
private Set<String> roles;
private String browser;
/**
* 用户信息
* 操作系统
*/
private SysUser sysUser;
private String os;
/**
* 菜单权限
*/
private Set<String> menuPermission;
/**
* 角色权限
*/
private Set<String> rolePermission;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
@JsonIgnore
private String password;
/**
* 角色对象
*/
private List<RoleDTO> roles;
/**
* 数据权限 当前角色ID
*/
private Long roleId;
/**
* 获取登录id
*/
public String getLoginId() {
return userType + CacheConstants.LOGINID_JOIN_CODE + userId;
}
}

View File

@@ -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;
}

View File

@@ -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<String, Object> rspMap = new HashMap<String, Object>();
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();
}

View File

@@ -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) {
}
}

View File

@@ -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个字符之间");
}

View File

@@ -17,6 +17,7 @@
<module>ruoyi-common-redis</module>
<module>ruoyi-common-swagger</module>
<module>ruoyi-common-security</module>
<module>ruoyi-common-satoken</module>
<module>ruoyi-common-datasource</module>
<module>ruoyi-common-web</module>
<module>ruoyi-common-mybatis</module>

View File

@@ -36,6 +36,12 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-satoken</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 多数据源 -->
<dependency>
<groupId>com.ruoyi</groupId>

View File

@@ -29,12 +29,6 @@
<artifactId>spring-web</artifactId>
</dependency>
<!-- Transmittable ThreadLocal -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
@@ -111,11 +105,6 @@
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-jwt</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>

View File

@@ -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;
}

View File

@@ -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<Map<String, Object>> THREAD_LOCAL = new TransmittableThreadLocal<>();
public static void set(String key, Object value) {
Map<String, Object> map = getLocalMap();
map.put(key, value == null ? StringUtils.EMPTY : value);
}
public static String get(String key) {
Map<String, Object> map = getLocalMap();
return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY));
}
public static <T> T get(String key, Class<T> clazz) {
Map<String, Object> map = getLocalMap();
return StringUtils.cast(map.getOrDefault(key, null));
}
public static Map<String, Object> getLocalMap() {
Map<String, Object> map = THREAD_LOCAL.get();
if (map == null) {
map = new ConcurrentHashMap<String, Object>();
THREAD_LOCAL.set(map);
}
return map;
}
public static void setLocalMap(Map<String, Object> 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();
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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() {
}
}

View File

@@ -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);
}
}

View File

@@ -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, ","));
}
}

View File

@@ -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, ","));
}
}

View File

@@ -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);
}
}

View File

@@ -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<String, Object> 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), "");
}
}

View File

@@ -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<String, String> 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;
}
}

View File

@@ -47,5 +47,18 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Sa-Token 整合 Dubbo -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-context-dubbo</artifactId>
<version>${satoken.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@@ -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

View File

@@ -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);
}

View File

@@ -22,6 +22,12 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-dubbo</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>

View File

@@ -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;

View File

@@ -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)) {

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>0.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common-satoken</artifactId>
<description>
ruoyi-common-satoken
</description>
<dependencies>
<!-- Sa-Token 权限认证core核心包, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId>
</dependency>
<!-- RuoYi Common Redis-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -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();
}
}

View File

@@ -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<String> searchData(String prefix, String keyword, int start, int size) {
Collection<String> keys = RedisUtils.keys(prefix + "*" + keyword + "*");
List<String> list = new ArrayList<>(keys);
return SaFoxUtil.searchList(list, start, size);
}
}

View File

@@ -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<String> 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<String> 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<>();
}
}

View File

@@ -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<LoginUser> 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);
}
}

View File

@@ -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

View File

@@ -16,31 +16,18 @@
<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId>
<version>${project.version}</version>
<artifactId>ruoyi-common-satoken</artifactId>
</dependency>
<!-- RuoYi Common Redis-->
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <artifactId>ruoyi-common-dubbo</artifactId>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->
</dependencies>
</project>

View File

@@ -11,8 +11,6 @@ import java.lang.annotation.*;
@Inherited
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
//// 指定要扫描的Mapper类的包的路径
//@MapperScan("com.ruoyi.**.mapper")
// 开启线程异步执行
@EnableAsync
public @interface EnableCustomConfig {

View File

@@ -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;
}

View File

@@ -1,18 +0,0 @@
package com.ruoyi.common.security.annotation;
/**
* 权限注解的验证模式
*
* @author ruoyi
*/
public enum Logical {
/**
* 必须具有所有的元素
*/
AND,
/**
* 只需具有其中一个元素
*/
OR
}

View File

@@ -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 {
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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<String> permissionList = getPermiList();
for (String permission : permissions) {
if (!hasPermi(permissionList, permission)) {
throw new NotPermissionException(permission);
}
}
}
/**
* 验证用户是否含有指定权限,只需包含其中一个
*
* @param permissions 权限码数组
*/
public void checkPermiOr(String... permissions) {
Set<String> 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<String> roleList = getRoleList();
for (String role : roles) {
if (!hasRole(roleList, role)) {
throw new NotRoleException(role);
}
}
}
/**
* 验证用户是否含有指定角色,只需包含其中一个
*
* @param roles 角色标识数组
*/
public void checkRoleOr(String... roles) {
Set<String> 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<String> getRoleList() {
try {
LoginUser loginUser = getLoginUser();
return loginUser.getRoles();
} catch (Exception e) {
return new HashSet<>();
}
}
/**
* 获取当前账号的权限列表
*
* @return 权限列表
*/
public Set<String> getPermiList() {
try {
LoginUser loginUser = getLoginUser();
return loginUser.getPermissions();
} catch (Exception e) {
return new HashSet<>();
}
}
/**
* 判断是否包含权限
*
* @param authorities 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(Collection<String> 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<String> roles, String role) {
return roles.stream().filter(StringUtils::isNotBlank)
.anyMatch(x -> SUPER_ADMIN.contains(x) || PatternMatchUtils.simpleMatch(x, role));
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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();
}
}

View File

@@ -1,14 +0,0 @@
package com.ruoyi.common.security.feign;
/**
* Feign 配置注册
*
* @author ruoyi
**/
//@Configuration
//public class DubboAutoConfiguration {
// @Bean
// public Filter requestInterceptor() {
// return new DubboRequestFilter();
// }
//}

View File

@@ -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<String, String> 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;
// }
//}

View File

@@ -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());
}
/**
* 演示模式异常
*/

View File

@@ -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();
}
}

View File

@@ -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<String, Object> 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<String, Object> claimsMap = new HashMap<String, Object>();
claimsMap.put(SecurityConstants.USER_KEY, token);
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
// 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>();
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;
}
}

View File

@@ -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;
}
/**
* 是否为管理员

View File

@@ -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

View File

@@ -63,6 +63,28 @@
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<!-- Sa-Token 权限认证Reactor响应式集成, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
<version>${satoken.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-satoken</artifactId>
</dependency>
<!-- RuoYi Common Redis-->
<dependency>
<groupId>com.ruoyi</groupId>
@@ -75,15 +97,6 @@
<!-- <artifactId>ruoyi-common-loadbalancer</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
</dependencies>

View File

@@ -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<Void> 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<Void> 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;
}
}
}

View File

@@ -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<Void> 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);
}
}

View File

@@ -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("验证码错误");
}
}
}

View File

@@ -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("(♥◠‿◠)ノ゙ 代码生成模块启动成功 ლ(´ڡ`ლ)゙ ");
}
}

View File

@@ -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<GenTable> 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<GenTable> 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<String, String> 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 {

View File

@@ -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<GenTable> tableList) {
String operName = SecurityUtils.getUsername();
String operName = LoginHelper.getUsername();
try {
for (GenTable table : tableList) {
String tableName = table.getTableName();

View File

@@ -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)

View File

@@ -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("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙ ");
}
}

View File

@@ -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<SysConfig> 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<SysConfig> 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() {

View File

@@ -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<SysDept> 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<SysDept> 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) {

View File

@@ -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<SysDictData> 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<SysDictData> 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) {

View File

@@ -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<SysDictType> 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<SysDictType> 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() {

View File

@@ -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<SysLogininfor> 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<SysLogininfor> 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));

View File

@@ -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<SysMenu> 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<SysMenu> 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<SysMenu> 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<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
return AjaxResult.success(menuService.buildMenus(menus));
}

View File

@@ -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<SysNotice> 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) {

View File

@@ -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<SysOperLog> 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<SysOperLog> 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));

View File

@@ -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<SysPost> 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<SysPost> 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) {

View File

@@ -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;
}
}

View File

@@ -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<SysRole> 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<SysRole> 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<SysUser> 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<SysUser> 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) {

View File

@@ -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<SysUser> 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<SysUser> 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<SysUserImportVo> 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<String> 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) {

View File

@@ -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<SysUserOnline> list(String ipaddr, String userName) {
Collection<String> keys = RedisUtils.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
// 获取所有未过期的 token
List<String> keys = StpUtil.searchTokenValue("", -1, 0);
List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
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();
}
}

View File

@@ -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<SysRoleDept> list = roleDeptMapper.selectList(
new LambdaQueryWrapper<SysRoleDept>()
.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<SysDept> list = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
.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;
}
}

View File

@@ -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<String> roles = permissionService.getRolePermission(sysUser.getUserId());
Set<String> rolePermission = permissionService.getRolePermission(sysUser.getUserId());
// 权限集合
Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
LoginUser sysUserVo = new LoginUser();
sysUserVo.setSysUser(sysUser);
sysUserVo.setRoles(roles);
sysUserVo.setPermissions(permissions);
return sysUserVo;
Set<String> 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<RoleDTO> roles = BeanUtil.copyToList(sysUser.getRoles(), RoleDTO.class);
loginUser.setRoles(roles);
return loginUser;
}
@Override

View File

@@ -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<SysUserImportVo
this.userService = SpringUtils.getBean(ISysUserService.class);
this.password = SecurityUtils.encryptPassword(initPassword);
this.isUpdateSupport = isUpdateSupport;
this.operName = SecurityUtils.getUsername();
this.operName = LoginHelper.getUsername();
}
@Override

View File

@@ -1,47 +1,47 @@
package com.ruoyi.system.service;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.domain.SysUserOnline;
/**
* 在线用户 服务层
*
* @author ruoyi
*/
public interface ISysUserOnlineService {
/**
* 通过登录地址查询信息
*
* @param ipaddr 登录地址
* @param user 用户信息
* @return 在线用户信息
*/
SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user);
/**
* 通过用户名称查询信息
*
* @param userName 用户名称
* @param user 用户信息
* @return 在线用户信息
*/
SysUserOnline selectOnlineByUserName(String userName, LoginUser user);
/**
* 通过登录地址/用户名称查询信息
*
* @param ipaddr 登录地址
* @param userName 用户名称
* @param user 用户信息
* @return 在线用户信息
*/
SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user);
/**
* 设置在线用户信息
*
* @param user 用户信息
* @return 在线用户
*/
SysUserOnline loginUserToUserOnline(LoginUser user);
}
package com.ruoyi.system.service;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.api.domain.SysUserOnline;
/**
* 在线用户 服务层
*
* @author ruoyi
*/
public interface ISysUserOnlineService {
/**
* 通过登录地址查询信息
*
* @param ipaddr 登录地址
* @param user 用户信息
* @return 在线用户信息
*/
SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user);
/**
* 通过用户名称查询信息
*
* @param userName 用户名称
* @param user 用户信息
* @return 在线用户信息
*/
SysUserOnline selectOnlineByUserName(String userName, LoginUser user);
/**
* 通过登录地址/用户名称查询信息
*
* @param ipaddr 登录地址
* @param userName 用户名称
* @param user 用户信息
* @return 在线用户信息
*/
SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user);
/**
* 设置在线用户信息
*
* @param user 用户信息
* @return 在线用户
*/
SysUserOnline loginUserToUserOnline(LoginUser user);
}

View File

@@ -11,7 +11,7 @@ import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.TreeBuildUtils;
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.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
@@ -153,7 +153,7 @@ public class SysDeptServiceImpl implements ISysDeptService {
*/
@Override
public void checkDeptDataScope(Long deptId) {
if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
if (!SysUser.isAdmin(LoginHelper.getUserId())) {
SysDept dept = new SysDept();
dept.setDeptId(deptId);
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);

View File

@@ -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<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);

View File

@@ -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;

View File

@@ -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<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);

View File

@@ -9,6 +9,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="deptId" column="dept_id" />
<result property="userName" column="user_name" />
<result property="nickName" column="nick_name" />
<result property="userType" column="user_type" />
<result property="email" column="email" />
<result property="phonenumber" column="phonenumber" />
<result property="sex" column="sex" />

View File

@@ -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
})
}
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
})
}

View File

@@ -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

View File

@@ -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, '测试员');
-- ----------------------------