!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

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