新增:app端鉴权,手机密码登录和手机验证码登录
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -128,6 +128,10 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
10
src/main/java/com/cool/core/enums/UserTypeEnum.java
Normal file
10
src/main/java/com/cool/core/enums/UserTypeEnum.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.cool.core.enums;
|
||||
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
public enum UserTypeEnum {
|
||||
ADMIN, // 后台
|
||||
APP, // app
|
||||
UNKNOWN, // 未知
|
||||
}
|
||||
@@ -49,6 +49,10 @@ public class CoolPreconditions {
|
||||
check(ObjectUtil.isEmpty(object), formatMessage(message, arguments));
|
||||
}
|
||||
|
||||
public static void checkEmpty(Object object) {
|
||||
check(ObjectUtil.isEmpty(object), "参数不能为空");
|
||||
}
|
||||
|
||||
private static String formatMessage(String messagePattern, Object... arguments) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int argumentIndex = 0;
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.cool.core.security;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import com.cool.core.annotation.TokenIgnore;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
/**
|
||||
* Token过滤器
|
||||
*/
|
||||
@Order(1)
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
final private JwtTokenUtil jwtTokenUtil;
|
||||
final private CoolCache coolCache;
|
||||
private final RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
HandlerExecutionChain handlerExecutionChain = requestMappingHandlerMapping.getHandler(request);
|
||||
if (handlerExecutionChain != null) {
|
||||
Object handler = handlerExecutionChain.getHandler();
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
if (handlerMethod.getMethodAnnotation(TokenIgnore.class) != null ||
|
||||
handlerMethod.getBeanType().getAnnotation(TokenIgnore.class) != null) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String authToken = request.getHeader("Authorization");
|
||||
if (!StrUtil.isEmpty(authToken)) {
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(authToken);
|
||||
|
||||
Object userType = jwt.getPayload("userType");
|
||||
if (Objects.equals(userType, UserTypeEnum.APP.name())) {
|
||||
// app
|
||||
handlerAppRequest(request, jwt, authToken);
|
||||
} else {
|
||||
// admin
|
||||
handlerAdminRequest(request, jwt, authToken);
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
/**
|
||||
* 处理app请求
|
||||
*/
|
||||
private void handlerAppRequest(HttpServletRequest request, JWT jwt, String authToken) {
|
||||
String userId = jwt.getPayload("userId").toString();
|
||||
if (ObjectUtil.isNotEmpty(userId)
|
||||
&& SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = coolCache.get("app:userDetails:" + userId,
|
||||
JwtUser.class);
|
||||
if (jwtTokenUtil.validateToken(authToken) && userDetails != null) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(
|
||||
new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理后台请求
|
||||
*/
|
||||
private void handlerAdminRequest(HttpServletRequest request, JWT jwt, String authToken) {
|
||||
String username = jwt.getPayload("username").toString();
|
||||
if (username != null
|
||||
&& SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = coolCache.get("admin:userDetails:" + username,
|
||||
JwtUser.class);
|
||||
Integer passwordV = Convert.toInt(jwt.getPayload("passwordVersion"));
|
||||
Integer rv = coolCache.get("admin:passwordVersion:" + jwt.getPayload("userId"),
|
||||
Integer.class);
|
||||
if (jwtTokenUtil.validateToken(authToken, username) && Objects.equals(passwordV, rv)
|
||||
&& userDetails != null) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(
|
||||
new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
request.setAttribute("adminUsername", jwt.getPayload("username"));
|
||||
request.setAttribute("adminUserId", jwt.getPayload("userId"));
|
||||
request.setAttribute("tokenInfo", jwt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
package com.cool.core.security;
|
||||
|
||||
import com.cool.core.annotation.TokenIgnore;
|
||||
import com.cool.modules.base.security.JwtAuthenticationTokenFilter;
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
@@ -51,7 +50,7 @@ public class JwtSecurityConfig {
|
||||
final private RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, ApplicationContext applicationContext) throws Exception {
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
|
||||
// 动态获取忽略的URL
|
||||
configureIgnoredUrls();
|
||||
|
||||
@@ -62,6 +61,7 @@ public class JwtSecurityConfig {
|
||||
ignoredUrlsProperties.getAdminAuthUrls().toArray(String[]::new))
|
||||
.permitAll();
|
||||
conf.requestMatchers("/admin/**").authenticated();
|
||||
conf.requestMatchers("/app/**").hasRole(UserTypeEnum.APP.name());
|
||||
})
|
||||
.headers(config -> config.frameOptions(FrameOptionsConfig::disable))
|
||||
// 允许网页iframe
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package com.cool.core.security.jwt;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import cn.hutool.jwt.JWTUtil;
|
||||
import cn.hutool.jwt.JWTValidator;
|
||||
import com.cool.core.config.CoolProperties;
|
||||
import com.cool.modules.base.service.sys.BaseSysConfService;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cool.modules.base.service.sys.BaseSysConfService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -23,7 +23,8 @@ public class JwtTokenUtil implements Serializable {
|
||||
|
||||
final private CoolProperties coolProperties;
|
||||
final private BaseSysConfService baseSysConfService;
|
||||
final String key = "JWT_SECRET";
|
||||
final String tokenKey = "JWT_SECRET_TOKEN";
|
||||
final String refreshTokenKey = "JWT_SECRET_REFRESH_TOKEN";
|
||||
|
||||
public long getExpire() {
|
||||
return this.coolProperties.getToken().getExpire();
|
||||
@@ -33,11 +34,20 @@ public class JwtTokenUtil implements Serializable {
|
||||
return this.coolProperties.getToken().getRefreshExpire();
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
String secret = baseSysConfService.getValueWithCache(key);
|
||||
public String getTokenSecret() {
|
||||
String secret = baseSysConfService.getValueWithCache(tokenKey);
|
||||
if (StrUtil.isBlank(secret)) {
|
||||
secret = StrUtil.uuid().replaceAll("-", "");
|
||||
baseSysConfService.setValue(key, secret);
|
||||
baseSysConfService.setValue(tokenKey, secret);
|
||||
}
|
||||
return secret;
|
||||
}
|
||||
|
||||
public String getRefreshTokenSecret() {
|
||||
String secret = baseSysConfService.getValueWithCache(refreshTokenKey);
|
||||
if (StrUtil.isBlank(secret)) {
|
||||
secret = StrUtil.uuid().replaceAll("-", "");
|
||||
baseSysConfService.setValue(refreshTokenKey, secret);
|
||||
}
|
||||
return secret;
|
||||
}
|
||||
@@ -51,7 +61,7 @@ public class JwtTokenUtil implements Serializable {
|
||||
public String generateToken(Map<String, Object> tokenInfo) {
|
||||
tokenInfo.put("isRefresh", false);
|
||||
Date expirationDate = new Date(System.currentTimeMillis() + getExpire() * 1000);
|
||||
JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getSecret().getBytes())
|
||||
JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getTokenSecret().getBytes())
|
||||
.setPayload("created", new Date());
|
||||
tokenInfo.forEach(jwt::setPayload);
|
||||
return jwt.sign();
|
||||
@@ -66,7 +76,7 @@ public class JwtTokenUtil implements Serializable {
|
||||
public String generateRefreshToken(Map<String, Object> tokenInfo) {
|
||||
tokenInfo.put("isRefresh", true);
|
||||
Date expirationDate = new Date(System.currentTimeMillis() + getRefreshExpire() * 1000);
|
||||
JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getSecret().getBytes())
|
||||
JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getRefreshTokenSecret().getBytes())
|
||||
.setPayload("created", new Date());
|
||||
tokenInfo.forEach(jwt::setPayload);
|
||||
return jwt.sign();
|
||||
@@ -116,8 +126,11 @@ public class JwtTokenUtil implements Serializable {
|
||||
* @return 是否有效
|
||||
*/
|
||||
public Boolean validateToken(String token, String username) {
|
||||
if (ObjectUtil.isEmpty(token)) {
|
||||
return false;
|
||||
}
|
||||
String tokenUsername = getUsernameFromToken(token);
|
||||
String secret = getSecret();
|
||||
String secret = getTokenSecret();
|
||||
boolean isValidSignature = JWTUtil.verify(token, secret.getBytes());
|
||||
return (tokenUsername.equals(username) && !isTokenExpired(token) && isValidSignature);
|
||||
}
|
||||
@@ -128,7 +141,24 @@ public class JwtTokenUtil implements Serializable {
|
||||
* @return
|
||||
*/
|
||||
public Boolean validateToken(String token) {
|
||||
String secret = getSecret();
|
||||
if (ObjectUtil.isEmpty(token)) {
|
||||
return false;
|
||||
}
|
||||
String secret = getTokenSecret();
|
||||
boolean isValidSignature = JWTUtil.verify(token, secret.getBytes());
|
||||
return (!isTokenExpired(token) && isValidSignature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验refresh token是否有效
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public Boolean validateRefreshToken(String token) {
|
||||
if (ObjectUtil.isEmpty(token)) {
|
||||
return false;
|
||||
}
|
||||
String secret = getRefreshTokenSecret();
|
||||
boolean isValidSignature = JWTUtil.verify(token, secret.getBytes());
|
||||
return (!isTokenExpired(token) && isValidSignature);
|
||||
}
|
||||
|
||||
@@ -1,29 +1,45 @@
|
||||
package com.cool.core.security.jwt;
|
||||
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
* 后台用户信息
|
||||
*/
|
||||
@Data
|
||||
public class JwtUser implements UserDetails {
|
||||
|
||||
public JwtUser(String username, String password, List<GrantedAuthority> perms, Boolean status) {
|
||||
/******
|
||||
* 后台用户
|
||||
* ********/
|
||||
private Long userId;
|
||||
private String username;
|
||||
private String password;
|
||||
private Boolean status;
|
||||
private UserTypeEnum userTypeEnum;
|
||||
private List<GrantedAuthority> perms;
|
||||
public JwtUser(Long userId, String username, String password, List<GrantedAuthority> perms, Boolean status) {
|
||||
this.userId = userId;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.perms = perms;
|
||||
this.status = status;
|
||||
this.userTypeEnum = UserTypeEnum.ADMIN;
|
||||
}
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
private Boolean status;
|
||||
private List<GrantedAuthority> perms;
|
||||
/******
|
||||
* app用户
|
||||
* ********/
|
||||
public JwtUser(Long userId, List<GrantedAuthority> perms, Boolean status) {
|
||||
this.userId = userId;
|
||||
this.perms = perms;
|
||||
this.status = status;
|
||||
this.userTypeEnum = UserTypeEnum.APP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
|
||||
102
src/main/java/com/cool/core/util/CoolSecurityUtil.java
Normal file
102
src/main/java/com/cool/core/util/CoolSecurityUtil.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package com.cool.core.util;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* Security 工具类
|
||||
*/
|
||||
public class CoolSecurityUtil {
|
||||
|
||||
private static final CoolCache coolCache = SpringUtil.getBean(CoolCache.class);
|
||||
|
||||
/***************后台********************/
|
||||
/**
|
||||
* 获取后台登录的用户名
|
||||
*/
|
||||
public static String getAdminUsername() {
|
||||
return SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得jwt中的信息
|
||||
*
|
||||
* @param requestParams 请求参数
|
||||
* @return jwt
|
||||
*/
|
||||
public static JSONObject getAdminUserInfo(JSONObject requestParams) {
|
||||
JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo");
|
||||
if (tokenInfo != null) {
|
||||
tokenInfo.set("department",
|
||||
coolCache.get("admin:department:" + tokenInfo.get("userId")));
|
||||
tokenInfo.set("roleIds", coolCache.get("admin:roleIds:" + tokenInfo.get("userId")));
|
||||
}
|
||||
return tokenInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台账号退出登录
|
||||
*
|
||||
* @param adminUserId 用户ID
|
||||
* @param username 用户名
|
||||
*/
|
||||
public static void adminLogout(Long adminUserId, String username) {
|
||||
coolCache.del("admin:department:" + adminUserId, "admin:passwordVersion:" + adminUserId,
|
||||
"admin:userInfo:" + adminUserId, "admin:userDetails:" + username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台账号退出登录
|
||||
*
|
||||
* @param userEntity 用户
|
||||
*/
|
||||
public static void adminLogout(BaseSysUserEntity userEntity) {
|
||||
adminLogout(userEntity.getId(), userEntity.getUsername());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前用户id
|
||||
*/
|
||||
public static Long getCurrentUserId() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof UserDetails) {
|
||||
return ((JwtUser) principal).getUserId();
|
||||
}
|
||||
}
|
||||
CoolPreconditions.check(true, 401, "未登录");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户类型
|
||||
*/
|
||||
public static UserTypeEnum getCurrentUserType() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof UserDetails) {
|
||||
return ((JwtUser) principal).getUserTypeEnum();
|
||||
}
|
||||
}
|
||||
// 还未登录,未知类型
|
||||
return UserTypeEnum.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* app退出登录,移除缓存信息
|
||||
*/
|
||||
public static void appLogout() {
|
||||
coolCache.del("app:userDetails"+ getCurrentUserId());
|
||||
}
|
||||
}
|
||||
47
src/main/java/com/cool/core/util/DatabaseDialectUtils.java
Normal file
47
src/main/java/com/cool/core/util/DatabaseDialectUtils.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package com.cool.core.util;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.tangzc.autotable.core.constants.DatabaseDialect;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* 获取数据库方言
|
||||
*/
|
||||
public class DatabaseDialectUtils {
|
||||
private static String dialect;
|
||||
|
||||
public static String getDatabaseDialect() {
|
||||
if (dialect == null) {
|
||||
dialect = determineDatabaseType();
|
||||
}
|
||||
return dialect;
|
||||
}
|
||||
|
||||
private static String determineDatabaseType() {
|
||||
// 从 DataSource 获取连接
|
||||
DataSource dataSource = SpringContextUtils.getBean(DataSource.class);
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
// 获取元数据
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
String productName = metaData.getDatabaseProductName();
|
||||
|
||||
return inferDatabaseTypeFromProductName(productName);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Failed to determine database dialect", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String inferDatabaseTypeFromProductName(String productName) {
|
||||
if (productName.startsWith(DatabaseDialect.MySQL)) {
|
||||
return DatabaseDialect.MySQL;
|
||||
} else if (productName.startsWith(DatabaseDialect.PostgreSQL)) {
|
||||
return DatabaseDialect.PostgreSQL;
|
||||
} else if (productName.startsWith(DatabaseDialect.SQLite)) {
|
||||
return DatabaseDialect.SQLite;
|
||||
}
|
||||
CoolPreconditions.alwaysThrow("暂不支持!");
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.cool.core.util;
|
||||
|
||||
import cn.hutool.core.annotation.AnnotationUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Editor;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
@@ -9,6 +12,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -78,6 +82,26 @@ public class EntityUtils {
|
||||
.filter(o -> !excludeList.contains(o.getName())).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将bean的部分属性转换成map<br>
|
||||
* 可选拷贝哪些属性值,默认是不忽略值为{@code null}的值的。
|
||||
*
|
||||
* @param bean bean
|
||||
* @param ignoreProperties 需要忽略拷贝的属性值,{@code null}或空表示拷贝所有值
|
||||
* @return Map
|
||||
* @since 5.8.0
|
||||
*/
|
||||
public static Map<String, Object> toMap(Object bean, String... ignoreProperties) {
|
||||
int mapSize = 16;
|
||||
Editor<String> keyEditor = null;
|
||||
final Set<String> propertiesSet = CollUtil.set(false, ignoreProperties);
|
||||
propertiesSet.add("queryWrapper");
|
||||
mapSize = ignoreProperties.length;
|
||||
keyEditor = property -> !propertiesSet.contains(property) ? property : null;
|
||||
// 指明了要复制的属性 所以不忽略null值
|
||||
return BeanUtil.beanToMap(bean, new LinkedHashMap<>(mapSize, 1), false, keyEditor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字段名是否在排除列表中
|
||||
*
|
||||
|
||||
@@ -92,6 +92,7 @@ public class AdminBaseCommController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@TokenIgnore
|
||||
@Operation(summary = "编程")
|
||||
@GetMapping("/program")
|
||||
public R program() {
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package com.cool.modules.base.controller.admin.sys;
|
||||
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY;
|
||||
import com.cool.modules.base.service.sys.BaseSysRoleService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 系统角色
|
||||
*/
|
||||
@@ -24,7 +26,10 @@ public class AdminBaseSysRoleController extends BaseController<BaseSysRoleServic
|
||||
|
||||
setPageOption(createOp().keyWordLikeFields(BASE_SYS_ROLE_ENTITY.NAME, BASE_SYS_ROLE_ENTITY.LABEL).queryWrapper(QueryWrapper.create().and(qw -> {
|
||||
qw.eq(BASE_SYS_ROLE_ENTITY.USER_ID.getName(), tokenInfo.get("userId")).or(w -> {
|
||||
w.in(BASE_SYS_ROLE_ENTITY.ID.getName(), tokenInfo.get("roleIds"));
|
||||
Object o = tokenInfo.get("roleIds");
|
||||
if (o != null) {
|
||||
w.in(BASE_SYS_ROLE_ENTITY.ID.getName(), new JSONArray(o).toList(Long.class));
|
||||
}
|
||||
});
|
||||
}, !isAdmin).and(BASE_SYS_ROLE_ENTITY.LABEL.ne("admin"))));
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.cool.modules.base.security;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Security 工具类
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CoolSecurityUtil {
|
||||
|
||||
final private CoolCache coolCache;
|
||||
|
||||
/**
|
||||
* 登录的用户名
|
||||
*
|
||||
* @return 用户名
|
||||
*/
|
||||
public String username() {
|
||||
return SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得jwt中的信息
|
||||
*
|
||||
* @param requestParams 请求参数
|
||||
* @return jwt
|
||||
*/
|
||||
public JSONObject userInfo(JSONObject requestParams) {
|
||||
JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo");
|
||||
if (tokenInfo != null) {
|
||||
tokenInfo.set("department",
|
||||
coolCache.get("admin:department:" + tokenInfo.get("userId")));
|
||||
tokenInfo.set("roleIds", coolCache.get("admin:roleIds:" + tokenInfo.get("userId")));
|
||||
}
|
||||
return tokenInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param adminUserId 用户ID
|
||||
* @param username 用户名
|
||||
*/
|
||||
public void logout(Long adminUserId, String username) {
|
||||
coolCache.del("admin:department:" + adminUserId, "admin:passwordVersion:" + adminUserId,
|
||||
"admin:userInfo:" + adminUserId, "admin:userDetails:" + username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param userEntity 用户
|
||||
*/
|
||||
public void logout(BaseSysUserEntity userEntity) {
|
||||
logout(userEntity.getId(), userEntity.getUsername());
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package com.cool.modules.base.security;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import com.cool.core.annotation.TokenIgnore;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
/**
|
||||
* Token过滤器
|
||||
*/
|
||||
@Order(1)
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
final private JwtTokenUtil jwtTokenUtil;
|
||||
final private CoolCache coolCache;
|
||||
private final RequestMappingHandlerMapping handlerMapping;
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
HandlerExecutionChain handlerExecutionChain = handlerMapping.getHandler(request);
|
||||
if (handlerExecutionChain != null) {
|
||||
Object handler = handlerExecutionChain.getHandler();
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
if (handlerMethod.getMethodAnnotation(TokenIgnore.class) != null ||
|
||||
handlerMethod.getBeanType().getAnnotation(TokenIgnore.class) != null) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String authToken = request.getHeader("Authorization");
|
||||
if (!StrUtil.isEmpty(authToken)) {
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(authToken);
|
||||
String username = jwt.getPayload("username").toString();
|
||||
if (username != null
|
||||
&& SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = coolCache.get("admin:userDetails:" + username,
|
||||
JwtUser.class);
|
||||
Integer passwordV = Convert.toInt(jwt.getPayload("passwordVersion"));
|
||||
Integer rv = coolCache.get("admin:passwordVersion:" + jwt.getPayload("userId"),
|
||||
Integer.class);
|
||||
if (jwtTokenUtil.validateToken(authToken, username) && Objects.equals(passwordV, rv)
|
||||
&& userDetails != null) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(
|
||||
new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
request.setAttribute("adminUsername", jwt.getPayload("username"));
|
||||
request.setAttribute("adminUserId", jwt.getPayload("userId"));
|
||||
request.setAttribute("tokenInfo", jwt);
|
||||
}
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class JwtUserDetailsServiceImpl implements UserDetailsService {
|
||||
authority.add(new SimpleGrantedAuthority(perm));
|
||||
}
|
||||
Long[] departmentIds = baseSysPermsService.getDepartmentIdsByRoleIds(sysUserEntity.getId());
|
||||
JwtUser jwtUser = new JwtUser(sysUserEntity.getUsername(), sysUserEntity.getPassword(),
|
||||
JwtUser jwtUser = new JwtUser(sysUserEntity.getId(), sysUserEntity.getUsername(), sysUserEntity.getPassword(),
|
||||
authority,
|
||||
sysUserEntity.getStatus() == 1);
|
||||
Long[] roleIds = baseSysPermsService.getRoles(sysUserEntity);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.cool.modules.base.security;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -53,13 +56,17 @@ public class MySecurityMetadataSource implements FilterInvocationSecurityMetadat
|
||||
*/
|
||||
@Override
|
||||
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
|
||||
UserTypeEnum userTypeEnum = CoolSecurityUtil.getCurrentUserType();
|
||||
if (ObjectUtil.equal(userTypeEnum, UserTypeEnum.APP)) {
|
||||
// app用户不需要权限拦截
|
||||
return null;
|
||||
}
|
||||
if (map == null) {
|
||||
loadResourceDefine();
|
||||
}
|
||||
// Object中包含用户请求request
|
||||
String url = ((FilterInvocation) o).getRequestUrl();
|
||||
return map.get(url.replace("/admin/", "").split("[?]")[0]);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,11 @@ public interface BaseSysLoginService {
|
||||
*/
|
||||
Object captcha(String type, Integer width, Integer height);
|
||||
|
||||
/**
|
||||
* 校验验证码
|
||||
*/
|
||||
void captchaCheck(String captchaId, String code);
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
|
||||
@@ -2,11 +2,11 @@ package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysDepartmentService;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
@@ -27,8 +27,6 @@ public class BaseSysDepartmentServiceImpl extends
|
||||
|
||||
final private BaseSysUserMapper baseSysUserMapper;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
@Override
|
||||
@@ -42,7 +40,7 @@ public class BaseSysDepartmentServiceImpl extends
|
||||
|
||||
@Override
|
||||
public List<BaseSysDepartmentEntity> list(JSONObject requestParams, QueryWrapper queryWrapper) {
|
||||
String username = coolSecurityUtil.username();
|
||||
String username = CoolSecurityUtil.getAdminUsername();
|
||||
Long[] loginDepartmentIds = baseSysPermsService.loginDepartmentIds();
|
||||
if (loginDepartmentIds != null && loginDepartmentIds.length == 0) {
|
||||
return new ArrayList<>();
|
||||
|
||||
@@ -7,13 +7,13 @@ import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.security.IgnoredUrlsProperties;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.core.util.IPUtils;
|
||||
import com.cool.modules.base.entity.sys.BaseSysLogEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.entity.sys.table.BaseSysLogEntityTableDef;
|
||||
import com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysLogMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysConfService;
|
||||
import com.cool.modules.base.service.sys.BaseSysLogService;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
@@ -35,8 +35,6 @@ public class BaseSysLogServiceImpl extends BaseServiceImpl<BaseSysLogMapper, Bas
|
||||
|
||||
private final BaseSysConfService baseSysConfService;
|
||||
|
||||
private final CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
private final IgnoredUrlsProperties ignoredUrlsProperties;
|
||||
|
||||
private final IPUtils ipUtils;
|
||||
@@ -78,7 +76,7 @@ public class BaseSysLogServiceImpl extends BaseServiceImpl<BaseSysLogMapper, Bas
|
||||
return;
|
||||
}
|
||||
String ipAddr = ipUtils.getIpAddr(request);
|
||||
JSONObject userInfo = coolSecurityUtil.userInfo(requestParams);
|
||||
JSONObject userInfo = CoolSecurityUtil.getAdminUserInfo(requestParams);
|
||||
|
||||
Long userId = null;
|
||||
if (userInfo != null) {
|
||||
|
||||
@@ -9,13 +9,13 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.exception.CoolException;
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.base.dto.sys.BaseSysLoginDto;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysLoginService;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
@@ -37,8 +37,6 @@ public class BaseSysLoginServiceImpl implements BaseSysLoginService {
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
private final CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
private final BaseSysUserMapper baseSysUserMapper;
|
||||
@@ -62,76 +60,73 @@ public class BaseSysLoginServiceImpl implements BaseSysLoginService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captchaCheck(String captchaId, String code) {
|
||||
String key = "verify:img:" + captchaId;
|
||||
String verifyCode = coolCache.get(key,
|
||||
String.class);
|
||||
boolean flag = StrUtil.isNotEmpty(verifyCode)
|
||||
&& verifyCode.equalsIgnoreCase(code);
|
||||
if (!flag) {
|
||||
coolCache.del(key);
|
||||
CoolPreconditions.alwaysThrow("验证码不正确");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object login(BaseSysLoginDto baseSysLoginDto) {
|
||||
// 1、检查验证码是否正确 2、执行登录操作
|
||||
String verifyCode = coolCache.get("verify:img:" + baseSysLoginDto.getCaptchaId(),
|
||||
String.class);
|
||||
if (StrUtil.isNotEmpty(verifyCode)
|
||||
&& verifyCode.equalsIgnoreCase(baseSysLoginDto.getVerifyCode())) {
|
||||
UsernamePasswordAuthenticationToken upToken =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
baseSysLoginDto.getUsername(), baseSysLoginDto.getPassword());
|
||||
Authentication authentication = authenticationManager.authenticate(upToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 查询用户信息并生成token
|
||||
BaseSysUserEntity sysUserEntity =
|
||||
baseSysUserMapper.selectOneByQuery(
|
||||
QueryWrapper.create()
|
||||
.eq(BaseSysUserEntity::getUsername, baseSysLoginDto.getUsername()));
|
||||
CoolPreconditions.check(
|
||||
ObjectUtil.isEmpty(sysUserEntity) || sysUserEntity.getStatus() == 0, "用户已禁用");
|
||||
Long[] roleIds = baseSysPermsService.getRoles(sysUserEntity);
|
||||
Dict tokenInfo =
|
||||
Dict.create()
|
||||
.set("roleIds", roleIds)
|
||||
.set("username", baseSysLoginDto.getUsername())
|
||||
.set("userId", sysUserEntity.getId())
|
||||
.set("passwordVersion", sysUserEntity.getPasswordV());
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
String refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
|
||||
coolCache.del("verify:img:" + baseSysLoginDto.getCaptchaId());
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire());
|
||||
} else {
|
||||
coolCache.del("verify:img:" + baseSysLoginDto.getCaptchaId());
|
||||
throw new CoolException("验证码不正确");
|
||||
}
|
||||
captchaCheck(baseSysLoginDto.getCaptchaId(), baseSysLoginDto.getVerifyCode());
|
||||
UsernamePasswordAuthenticationToken upToken =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
baseSysLoginDto.getUsername(), baseSysLoginDto.getPassword());
|
||||
Authentication authentication = authenticationManager.authenticate(upToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 查询用户信息并生成token
|
||||
BaseSysUserEntity baseSysUserEntity =
|
||||
baseSysUserMapper.selectOneByQuery(
|
||||
QueryWrapper.create()
|
||||
.eq(BaseSysUserEntity::getUsername, baseSysLoginDto.getUsername()));
|
||||
CoolPreconditions.check(
|
||||
ObjectUtil.isEmpty(baseSysUserEntity) || baseSysUserEntity.getStatus() == 0, "用户已禁用");
|
||||
Long[] roleIds = baseSysPermsService.getRoles(baseSysUserEntity);
|
||||
coolCache.del("verify:img:" + baseSysLoginDto.getCaptchaId());
|
||||
return generateToken(roleIds, baseSysUserEntity, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(Long adminUserId, String username) {
|
||||
coolSecurityUtil.logout(adminUserId, username);
|
||||
CoolSecurityUtil.adminLogout(adminUserId, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object refreshToken(String refreshToken) {
|
||||
CoolPreconditions.check(!jwtTokenUtil.validateRefreshToken(refreshToken), "错误的refreshToken");
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken);
|
||||
try {
|
||||
CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"),
|
||||
"错误的token");
|
||||
CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"),
|
||||
"错误的refreshToken");
|
||||
BaseSysUserEntity baseSysUserEntity =
|
||||
baseSysUserMapper.selectOneById(Convert.toLong(jwt.getPayload("userId")));
|
||||
Long[] roleIds = baseSysPermsService.getRoles(baseSysUserEntity);
|
||||
return generateToken(roleIds, baseSysUserEntity, refreshToken);
|
||||
}
|
||||
|
||||
BaseSysUserEntity baseSysUserEntity =
|
||||
baseSysUserMapper.selectOneById(Convert.toLong(jwt.getPayload("userId")));
|
||||
Long[] roleIds = baseSysPermsService.getRoles(baseSysUserEntity);
|
||||
Dict tokenInfo =
|
||||
Dict.create()
|
||||
.set("roleIds", roleIds)
|
||||
.set("username", baseSysUserEntity.getUsername())
|
||||
.set("userId", baseSysUserEntity.getId())
|
||||
.set("passwordVersion", baseSysUserEntity.getPasswordV());
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
private Dict generateToken(Long[] roleIds, BaseSysUserEntity baseSysUserEntity, String refreshToken) {
|
||||
Dict tokenInfo =
|
||||
Dict.create()
|
||||
.set("userType", UserTypeEnum.ADMIN.name())
|
||||
.set("roleIds", roleIds)
|
||||
.set("username", baseSysUserEntity.getUsername())
|
||||
.set("userId", baseSysUserEntity.getId())
|
||||
.set("passwordVersion", baseSysUserEntity.getPasswordV());
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
if (StrUtil.isEmpty(refreshToken)) {
|
||||
refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire());
|
||||
} catch (Exception e) {
|
||||
throw new CoolException("错误的token", e);
|
||||
}
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.ModifyEnum;
|
||||
import com.cool.core.eps.CoolEps;
|
||||
import com.cool.core.util.CompilerUtils;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.core.util.PathUtils;
|
||||
import com.cool.modules.base.entity.sys.BaseSysMenuEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysMenuMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysMenuService;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
@@ -33,13 +33,11 @@ public class BaseSysMenuServiceImpl extends BaseServiceImpl<BaseSysMenuMapper, B
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
final private CoolEps coolEps;
|
||||
|
||||
@Override
|
||||
public Object list(JSONObject requestParams, QueryWrapper queryWrapper) {
|
||||
List<BaseSysMenuEntity> list = baseSysPermsService.getMenus(coolSecurityUtil.username());
|
||||
List<BaseSysMenuEntity> list = baseSysPermsService.getMenus(CoolSecurityUtil.getAdminUsername());
|
||||
list.forEach(e -> {
|
||||
List<BaseSysMenuEntity> parent = list.stream()
|
||||
.filter(sysMenuEntity -> e.getParentId() != null && e.getParentId()
|
||||
|
||||
@@ -11,10 +11,10 @@ import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.core.util.SpringContextUtils;
|
||||
import com.cool.modules.base.entity.sys.*;
|
||||
import com.cool.modules.base.mapper.sys.*;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.row.Row;
|
||||
@@ -41,11 +41,9 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService {
|
||||
|
||||
final private BaseSysDepartmentMapper baseSysDepartmentMapper;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
@Override
|
||||
public Long[] loginDepartmentIds() {
|
||||
String username = coolSecurityUtil.username();
|
||||
String username = CoolSecurityUtil.getAdminUsername();
|
||||
if (username.equals("admin")) {
|
||||
return baseSysDepartmentMapper.selectAll().stream().map(BaseSysDepartmentEntity::getId)
|
||||
.toArray(Long[]::new);
|
||||
@@ -64,8 +62,11 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService {
|
||||
}
|
||||
|
||||
private Long[] getLongs(Long[] roleIds) {
|
||||
if (ObjectUtil.isEmpty(roleIds)) {
|
||||
return new Long[]{};
|
||||
}
|
||||
QueryWrapper queryWrapper = QueryWrapper.create();
|
||||
if (roleIds != null && !CollUtil.toList(roleIds).contains(1L)) {
|
||||
if (!CollUtil.toList(roleIds).contains(1L)) {
|
||||
queryWrapper.in(BaseSysRoleDepartmentEntity::getRoleId, (Object) roleIds);
|
||||
}
|
||||
return baseSysRoleDepartmentMapper
|
||||
@@ -217,7 +218,7 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService {
|
||||
SpringContextUtils.getBean(UserDetailsService.class).loadUserByUsername(baseSysUserEntity.getUsername());
|
||||
}
|
||||
if (baseSysUserEntity != null && baseSysUserEntity.getStatus() == 0) {
|
||||
coolSecurityUtil.logout(baseSysUserEntity.getId(), baseSysUserEntity.getUsername());
|
||||
CoolSecurityUtil.adminLogout(baseSysUserEntity.getId(), baseSysUserEntity.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,21 +5,20 @@ import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.ModifyEnum;
|
||||
import com.cool.core.exception.CoolException;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleDepartmentEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleMenuEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysRoleDepartmentMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysRoleMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysRoleMenuMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.cool.modules.base.service.sys.BaseSysRoleService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统角色
|
||||
*/
|
||||
@@ -36,15 +35,13 @@ public class BaseSysRoleServiceImpl extends BaseServiceImpl<BaseSysRoleMapper, B
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
@Override
|
||||
public Object add(JSONObject requestParams, BaseSysRoleEntity entity) {
|
||||
BaseSysRoleEntity checkLabel = getOne(QueryWrapper.create().eq(BaseSysRoleEntity::getLabel, entity.getLabel()));
|
||||
if (checkLabel != null) {
|
||||
throw new CoolException("标识已存在");
|
||||
}
|
||||
entity.setUserId((coolSecurityUtil.userInfo(requestParams).getLong("userId")));
|
||||
entity.setUserId((CoolSecurityUtil.getAdminUserInfo(requestParams).getLong("userId")));
|
||||
return super.add(requestParams, entity);
|
||||
}
|
||||
|
||||
@@ -83,10 +80,11 @@ public class BaseSysRoleServiceImpl extends BaseServiceImpl<BaseSysRoleMapper, B
|
||||
@Override
|
||||
public Object list(JSONObject requestParams, QueryWrapper queryWrapper) {
|
||||
return baseSysRoleMapper.selectListByQuery(queryWrapper.ne(BaseSysRoleEntity::getId, 1L).and(qw -> {
|
||||
qw.eq(BaseSysRoleEntity::getUserId, coolSecurityUtil.userInfo(requestParams).get("userId")).or(w -> {
|
||||
JSONObject object = CoolSecurityUtil.getAdminUserInfo(requestParams);
|
||||
qw.eq(BaseSysRoleEntity::getUserId, object.get("userId")).or(w -> {
|
||||
w.in(BaseSysRoleEntity::getId,
|
||||
(Object) coolSecurityUtil.userInfo(requestParams).get("roleIds", Long[].class));
|
||||
(Object) object.get("roleIds", Long[].class));
|
||||
});
|
||||
}, !coolSecurityUtil.username().equals("admin")));
|
||||
}, !CoolSecurityUtil.getAdminUsername().equals("admin")));
|
||||
}
|
||||
}
|
||||
@@ -15,18 +15,19 @@ import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.ModifyEnum;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.core.util.DatabaseDialectUtils;
|
||||
import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.cool.modules.base.service.sys.BaseSysUserService;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.update.UpdateChain;
|
||||
import com.tangzc.autotable.core.constants.DatabaseDialect;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@@ -39,30 +40,27 @@ public class BaseSysUserServiceImpl extends BaseServiceImpl<BaseSysUserMapper, B
|
||||
|
||||
final private CoolCache coolCache;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
final private BaseSysDepartmentMapper baseSysDepartmentMapper;
|
||||
|
||||
@Value("${spring.datasource.url}")
|
||||
private String datasourceUrl;
|
||||
|
||||
@Override
|
||||
public Object page(JSONObject requestParams, Page<BaseSysUserEntity> page, QueryWrapper qw) {
|
||||
String keyWord = requestParams.getStr("keyWord");
|
||||
Integer status = requestParams.getInt("status");
|
||||
Long[] departmentIds = requestParams.get("departmentIds", Long[].class);
|
||||
JSONObject tokenInfo = coolSecurityUtil.userInfo(requestParams);
|
||||
JSONObject tokenInfo = CoolSecurityUtil.getAdminUserInfo(requestParams);
|
||||
// 用户的部门权限
|
||||
Long[] permsDepartmentArr = coolCache.get("admin:department:" + tokenInfo.get("userId"),
|
||||
Long[].class);
|
||||
// TODO 临时兼容 postgresql
|
||||
if (datasourceUrl.contains("postgresql")) {
|
||||
qw.select(BASE_SYS_USER_ENTITY.ALL_COLUMNS
|
||||
// ,
|
||||
// groupConcat(BASE_SYS_ROLE_ENTITY.NAME).as("roleName"),
|
||||
// BASE_SYS_DEPARTMENT_ENTITY.NAME.as("departmentName")
|
||||
String databaseDialect = DatabaseDialectUtils.getDatabaseDialect();
|
||||
if (databaseDialect.equals(DatabaseDialect.PostgreSQL)) {
|
||||
qw.select("base_sys_user.id","base_sys_user.create_time","base_sys_user.department_id",
|
||||
"base_sys_user.email","base_sys_user.head_img","base_sys_user.name","base_sys_user.nick_name",
|
||||
"base_sys_user.phone","base_sys_user.remark","base_sys_user.status",
|
||||
"base_sys_user.update_time","base_sys_user.username",
|
||||
"string_agg(base_sys_role.name, ', ') AS roleName",
|
||||
"base_sys_department.name AS departmentName"
|
||||
);
|
||||
} else {
|
||||
qw.select(BASE_SYS_USER_ENTITY.ALL_COLUMNS,
|
||||
@@ -94,9 +92,16 @@ public class BaseSysUserServiceImpl extends BaseServiceImpl<BaseSysUserMapper, B
|
||||
qw.and(BASE_SYS_USER_ENTITY.DEPARTMENT_ID.in(
|
||||
permsDepartmentArr == null || permsDepartmentArr.length == 0 ? new Long[]{null}
|
||||
: permsDepartmentArr,
|
||||
!coolSecurityUtil.username().equals("admin")));
|
||||
|
||||
qw.groupBy(BASE_SYS_USER_ENTITY.ID);
|
||||
!CoolSecurityUtil.getAdminUsername().equals("admin")));
|
||||
if (databaseDialect.equals(DatabaseDialect.PostgreSQL)) {
|
||||
qw.groupBy("base_sys_user.id","base_sys_user.create_time","base_sys_user.department_id",
|
||||
"base_sys_user.email","base_sys_user.head_img","base_sys_user.name","base_sys_user.nick_name",
|
||||
"base_sys_user.phone","base_sys_user.remark","base_sys_user.status",
|
||||
"base_sys_user.update_time","base_sys_user.username",
|
||||
"base_sys_department.name");
|
||||
} else {
|
||||
qw.groupBy(BASE_SYS_USER_ENTITY.ID);
|
||||
}
|
||||
return mapper.paginate(page, qw);
|
||||
}
|
||||
|
||||
@@ -148,7 +153,7 @@ public class BaseSysUserServiceImpl extends BaseServiceImpl<BaseSysUserMapper, B
|
||||
}
|
||||
// 被禁用
|
||||
if (entity.getStatus() == 0) {
|
||||
coolSecurityUtil.logout(entity);
|
||||
CoolSecurityUtil.adminLogout(entity);
|
||||
}
|
||||
return super.update(requestParams, entity);
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
//package com.cool.modules.recycle.aop;
|
||||
//
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
//
|
||||
//@Configuration
|
||||
//@EnableAspectJAutoProxy
|
||||
//public class AopConfig {
|
||||
//
|
||||
// @Bean
|
||||
// public DeleteAspect deleteAspect() {
|
||||
// return new DeleteAspect();
|
||||
// }
|
||||
//}
|
||||
@@ -6,7 +6,7 @@ import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.IgnoreRecycleData;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.recycle.entity.RecycleDataEntity;
|
||||
import com.cool.modules.recycle.service.RecycleDataService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
@@ -35,8 +35,6 @@ public class DeleteAspect {
|
||||
|
||||
final private RecycleDataService recycleDataService;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
@Around(value = "execution(* com.cool.core.base.BaseController.delete*(..)) && args(request, params, requestParams)", argNames = "joinPoint,request,params,requestParams")
|
||||
public Object aroundAdvice(ProceedingJoinPoint joinPoint, HttpServletRequest request,
|
||||
Map<String, Object> params,
|
||||
@@ -71,10 +69,10 @@ public class DeleteAspect {
|
||||
if (ObjUtil.isNotEmpty(list)) {
|
||||
RecycleDataEntity recycleDataEntity = new RecycleDataEntity();
|
||||
recycleDataEntity.setUrl(request.getRequestURI());
|
||||
recycleDataEntity.setUserName(coolSecurityUtil.username());
|
||||
recycleDataEntity.setUserName(CoolSecurityUtil.getAdminUsername());
|
||||
recycleDataEntity
|
||||
.setUserId(Long.parseLong(
|
||||
String.valueOf(coolSecurityUtil.userInfo(requestParams).get("userId"))));
|
||||
String.valueOf(CoolSecurityUtil.getAdminUserInfo(requestParams).get("userId"))));
|
||||
recycleDataEntity.setParams(params);
|
||||
recycleDataEntity.setData(list);
|
||||
recycleDataEntity.setParams(params);
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
package com.cool.modules.user.controller.app;
|
||||
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.core.util.EntityUtils;
|
||||
import com.cool.modules.user.entity.UserInfoEntity;
|
||||
import com.cool.modules.user.service.UserInfoService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "用户信息", description = "用户信息")
|
||||
@CoolRestController()
|
||||
@CoolRestController
|
||||
public class AppUserInfoController {
|
||||
|
||||
private final UserInfoService userInfoService;
|
||||
|
||||
@Operation(summary = "用户个人信息", description = "获得App、小程序或者其他应用的用户个人信息")
|
||||
@GetMapping("/person")
|
||||
public Object person(@RequestAttribute("appUserId") Long appUserId) {
|
||||
return userInfoService.person(appUserId);
|
||||
public R person() {
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
UserInfoEntity userInfoEntity = userInfoService.person(userId);
|
||||
return R.ok(EntityUtils.toMap(userInfoEntity,
|
||||
"password"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
package com.cool.modules.user.controller.app;
|
||||
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.annotation.TokenIgnore;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.base.service.sys.BaseSysLoginService;
|
||||
import com.cool.modules.user.controller.app.params.CaptchaParam;
|
||||
import com.cool.modules.user.controller.app.params.LoginParam;
|
||||
import com.cool.modules.user.controller.app.params.RefreshTokenParam;
|
||||
import com.cool.modules.user.controller.app.params.SmsCodeParam;
|
||||
import com.cool.modules.user.service.UserLoginService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "用户登录", description = "用户登录")
|
||||
@CoolRestController
|
||||
public class AppUserLoginController {
|
||||
|
||||
private final UserLoginService userLoginService;
|
||||
|
||||
private final BaseSysLoginService baseSysLoginService;
|
||||
|
||||
/**
|
||||
* 小程序登录
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "小程序登录")
|
||||
@PostMapping("/mini")
|
||||
public R mini(@RequestBody LoginParam param) {
|
||||
String code = param.getCode();
|
||||
String encryptedData = param.getEncryptedData();
|
||||
String iv = param.getIv();
|
||||
CoolPreconditions.checkEmpty(code);
|
||||
CoolPreconditions.checkEmpty(encryptedData);
|
||||
CoolPreconditions.checkEmpty(iv);
|
||||
return R.ok(userLoginService.mini(code, encryptedData, iv));
|
||||
}
|
||||
|
||||
/**
|
||||
* 公众号登录
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "公众号登录")
|
||||
@PostMapping("/mp")
|
||||
public R mp(@RequestBody LoginParam param) {
|
||||
String code = param.getCode();
|
||||
CoolPreconditions.checkEmpty(code);
|
||||
return R.ok(userLoginService.mp(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信APP授权登录
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "微信APP授权登录")
|
||||
@PostMapping("/wxApp")
|
||||
public R wxApp(@RequestBody LoginParam param) {
|
||||
String code = param.getCode();
|
||||
CoolPreconditions.checkEmpty(code);
|
||||
return R.ok(userLoginService.wxApp(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号登录
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "手机号登录")
|
||||
@PostMapping("/phone")
|
||||
public R phone(
|
||||
@RequestBody LoginParam param) {
|
||||
String phone = param.getPhone();
|
||||
String smsCode = param.getSmsCode();
|
||||
CoolPreconditions.checkEmpty(phone);
|
||||
CoolPreconditions.checkEmpty(smsCode);
|
||||
return R.ok(userLoginService.phoneVerifyCode(phone, smsCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键手机号登录
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "一键手机号登录")
|
||||
@PostMapping("/uniPhone")
|
||||
public R uniPhone(
|
||||
@RequestBody LoginParam param) {
|
||||
String accessToken = param.getAccess_token();
|
||||
String openid = param.getOpenid();
|
||||
String appId = param.getAppId();
|
||||
CoolPreconditions.checkEmpty(accessToken);
|
||||
CoolPreconditions.checkEmpty(openid);
|
||||
CoolPreconditions.checkEmpty(appId);
|
||||
return R.ok(userLoginService.uniPhone(accessToken, openid, appId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定小程序手机号
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "绑定小程序手机号")
|
||||
@PostMapping("/miniPhone")
|
||||
public R miniPhone(@RequestBody LoginParam param) {
|
||||
String code = param.getCode();
|
||||
String encryptedData = param.getEncryptedData();
|
||||
String iv = param.getIv();
|
||||
CoolPreconditions.checkEmpty(code);
|
||||
CoolPreconditions.checkEmpty(encryptedData);
|
||||
CoolPreconditions.checkEmpty(iv);
|
||||
return R.ok(userLoginService.miniPhone(code, encryptedData, iv));
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片验证码
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "图片验证码")
|
||||
@GetMapping("/captcha")
|
||||
public R captcha(
|
||||
@RequestBody CaptchaParam param) {
|
||||
String type = param.getType();
|
||||
Integer width = param.getWidth();
|
||||
Integer height = param.getHeight();
|
||||
|
||||
CoolPreconditions.checkEmpty(type);
|
||||
CoolPreconditions.checkEmpty(width);
|
||||
CoolPreconditions.checkEmpty(height);
|
||||
|
||||
return R.ok(baseSysLoginService.captcha(type, width, height));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "验证码")
|
||||
@PostMapping("/smsCode")
|
||||
public R smsCode(
|
||||
@RequestBody SmsCodeParam param) {
|
||||
String phone = param.getPhone();
|
||||
String captchaId = param.getCaptchaId();
|
||||
String code = param.getCode();
|
||||
|
||||
CoolPreconditions.checkEmpty(phone);
|
||||
CoolPreconditions.checkEmpty(captchaId);
|
||||
CoolPreconditions.checkEmpty(code);
|
||||
userLoginService.smsCode(phone, captchaId, code);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "刷新token")
|
||||
@PostMapping("/refreshToken")
|
||||
public R refreshToken(@RequestBody RefreshTokenParam param) {
|
||||
return R.ok(userLoginService.refreshToken(param.getRefreshToken()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码登录
|
||||
*/
|
||||
@TokenIgnore
|
||||
@Operation(summary = "密码登录")
|
||||
@PostMapping("/password")
|
||||
public R password(
|
||||
@RequestBody LoginParam param) {
|
||||
String phone = param.getPhone();
|
||||
String password = param.getPassword();
|
||||
|
||||
CoolPreconditions.checkEmpty(phone);
|
||||
CoolPreconditions.checkEmpty(password);
|
||||
return R.ok(userLoginService.password(phone, password));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.user.controller.app.params;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class CaptchaParam {
|
||||
private String type;
|
||||
private Integer width;
|
||||
private Integer height;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.cool.modules.user.controller.app.params;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class LoginParam {
|
||||
|
||||
/*******小程序/公众号/微信APP授权 登录*******/
|
||||
private String code;
|
||||
|
||||
private String encryptedData;
|
||||
|
||||
private String iv;
|
||||
|
||||
|
||||
/*******手机号登录*******/
|
||||
private String phone;
|
||||
|
||||
private String smsCode;
|
||||
|
||||
|
||||
/*******一键手机号登录*******/
|
||||
private String access_token;
|
||||
|
||||
private String openid;
|
||||
|
||||
private String appId;
|
||||
|
||||
|
||||
/*******密码登录*******/
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.cool.modules.user.controller.app.params;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class RefreshTokenParam {
|
||||
private String refreshToken;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.user.controller.app.params;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class SmsCodeParam {
|
||||
private String phone;
|
||||
private String captchaId;
|
||||
private String code;
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.cool.modules.user.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import com.tangzc.autotable.annotation.enums.IndexTypeEnum;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@@ -13,18 +12,18 @@ import lombok.Setter;
|
||||
@Table(value = "user_info", comment = "用户信息")
|
||||
public class UserInfoEntity extends BaseEntity<UserInfoEntity> {
|
||||
|
||||
@Index(type = IndexTypeEnum.UNIQUE)
|
||||
@ColumnDefine(comment = "登录唯一ID", notNull = true)
|
||||
@UniIndex
|
||||
@ColumnDefine(comment = "登录唯一ID")
|
||||
private String unionid;
|
||||
|
||||
@ColumnDefine(comment = "头像", notNull = true)
|
||||
@ColumnDefine(comment = "头像")
|
||||
private String avatarUrl;
|
||||
|
||||
@ColumnDefine(comment = "昵称", notNull = true)
|
||||
@ColumnDefine(comment = "昵称")
|
||||
private String nickName;
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "手机号", notNull = true)
|
||||
@UniIndex
|
||||
@ColumnDefine(comment = "手机号")
|
||||
private String phone;
|
||||
|
||||
@ColumnDefine(comment = "性别 0-未知 1-男 2-女", defaultValue = "0")
|
||||
@@ -36,6 +35,6 @@ public class UserInfoEntity extends BaseEntity<UserInfoEntity> {
|
||||
@ColumnDefine(comment = "登录方式 0-小程序 1-公众号 2-H5", defaultValue = "0")
|
||||
private String loginType;
|
||||
|
||||
@ColumnDefine(comment = "密码", notNull = true)
|
||||
@ColumnDefine(comment = "密码")
|
||||
private String password;
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ public interface UserInfoService extends BaseService<UserInfoEntity> {
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
Object person(Long userId);
|
||||
UserInfoEntity person(Long userId);
|
||||
}
|
||||
|
||||
@@ -28,4 +28,30 @@ public interface UserLoginService {
|
||||
* @return 新的token
|
||||
*/
|
||||
Object refreshToken(String refreshToken);
|
||||
/**
|
||||
* 小程序登录
|
||||
*/
|
||||
Object mini(String code, String encryptedData, String iv);
|
||||
/**
|
||||
* 公众号登录
|
||||
*/
|
||||
Object mp(String code);
|
||||
/**
|
||||
* 微信APP授权登录
|
||||
*/
|
||||
Object wxApp(String code);
|
||||
|
||||
/**
|
||||
* 一键手机号登录
|
||||
*/
|
||||
Object uniPhone(String accessToken, String openid, String appId);
|
||||
/**
|
||||
* 绑定小程序手机号
|
||||
*/
|
||||
Object miniPhone(String code, String encryptedData, String iv);
|
||||
|
||||
/**
|
||||
* 密码登录
|
||||
*/
|
||||
Object password(String phone, String password);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class UserInfoServiceImpl extends BaseServiceImpl<UserInfoMapper, UserInf
|
||||
UserInfoService {
|
||||
|
||||
@Override
|
||||
public Object person(Long userId) {
|
||||
public UserInfoEntity person(Long userId) {
|
||||
UserInfoEntity info = mapper.selectOneById(userId);
|
||||
info.setPassword(null);
|
||||
return info;
|
||||
|
||||
@@ -2,17 +2,25 @@ package com.cool.modules.user.service.impl;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.exception.CoolException;
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import com.cool.modules.base.service.sys.BaseSysLoginService;
|
||||
import com.cool.modules.user.entity.UserInfoEntity;
|
||||
import com.cool.modules.user.mapper.UserInfoMapper;
|
||||
import com.cool.modules.user.service.UserLoginService;
|
||||
import com.cool.modules.user.util.UserSmsUtil;
|
||||
import com.cool.modules.user.util.UserSmsUtil.SendSceneEnum;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -21,45 +29,112 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
|
||||
private final CoolCache coolCache;
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
private final CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
private final UserInfoMapper userInfoMapper;
|
||||
|
||||
private final UserSmsUtil userSmsUtil;
|
||||
|
||||
private final BaseSysLoginService baseSysLoginService;
|
||||
private final static List<GrantedAuthority> authority =
|
||||
List.of(new SimpleGrantedAuthority("ROLE_" + UserTypeEnum.APP.name()));
|
||||
|
||||
@Override
|
||||
public void smsCode(String phone, String captchaId, String code) {
|
||||
|
||||
// 校验图片验证码,不通过直接抛异常
|
||||
baseSysLoginService.captchaCheck(captchaId, code);
|
||||
userSmsUtil.sendVerifyCode(phone, SendSceneEnum.login);
|
||||
coolCache.del("verify:img:" + captchaId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object phoneVerifyCode(String phone, String smsCode) {
|
||||
// 校验短信验证码,不通过直接抛异常
|
||||
userSmsUtil.checkVerifyCode(phone, smsCode, SendSceneEnum.login);
|
||||
return generateTokenByPhone(phone);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object refreshToken(String refreshToken) {
|
||||
CoolPreconditions.check(!jwtTokenUtil.validateRefreshToken(refreshToken), "错误的refreshToken");
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken);
|
||||
CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"),
|
||||
"错误的refreshToken");
|
||||
Long userId = Convert.toLong(jwt.getPayload("userId"));
|
||||
return generateToken(userId, refreshToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object mini(String code, String encryptedData, String iv) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object refreshToken(String refreshToken) {
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken);
|
||||
try {
|
||||
CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"),
|
||||
"错误的token");
|
||||
public Object mp(String code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
UserInfoEntity userInfoEntity =
|
||||
userInfoMapper.selectOneById(Convert.toLong(jwt.getPayload("userId")));
|
||||
Dict tokenInfo =
|
||||
Dict.create()
|
||||
.set("userId", userInfoEntity.getId());
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire());
|
||||
} catch (Exception e) {
|
||||
throw new CoolException("错误的token", e);
|
||||
@Override
|
||||
public Object wxApp(String code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object uniPhone(String accessToken, String openid, String appId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object miniPhone(String code, String encryptedData, String iv) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object password(String phone, String password) {
|
||||
UserInfoEntity userInfoEntity = userInfoMapper.selectOneByQuery(
|
||||
QueryWrapper.create().eq(UserInfoEntity::getPhone, phone));
|
||||
CoolPreconditions.checkEmpty(userInfoEntity, "账号或密码错误");
|
||||
if (userInfoEntity.getPassword().equals(MD5.create().digestHex(password))) {
|
||||
return generateToken(userInfoEntity, null);
|
||||
}
|
||||
CoolPreconditions.checkEmpty(userInfoEntity, "账号或密码错误");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置已校验用户的手机号,
|
||||
* 根据手机号找到用户生成token
|
||||
*/
|
||||
private Object generateTokenByPhone(String phone) {
|
||||
UserInfoEntity userInfoEntity = userInfoMapper.selectOneByQuery(
|
||||
QueryWrapper.create().eq(UserInfoEntity::getPhone, phone));
|
||||
return generateToken(userInfoEntity, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
*/
|
||||
private Dict generateToken(Long userId, String refreshToken) {
|
||||
UserInfoEntity userInfoEntity = userInfoMapper.selectOneById(userId);
|
||||
return generateToken(userInfoEntity, refreshToken);
|
||||
}
|
||||
private Dict generateToken(UserInfoEntity userInfoEntity, String refreshToken) {
|
||||
Dict tokenInfo = Dict.create()
|
||||
.set("userType", UserTypeEnum.APP.name())
|
||||
.set("userId", userInfoEntity.getId());
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
if (ObjUtil.isEmpty(refreshToken)) {
|
||||
refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
|
||||
}
|
||||
JwtUser jwtUser = new JwtUser(userInfoEntity.getId(),
|
||||
authority,
|
||||
ObjUtil.equals(userInfoEntity.getStatus(), 1));
|
||||
coolCache.set("app:userDetails:" + jwtUser.getUserId(), jwtUser);
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.cool.modules.user.token;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import com.cool.core.annotation.TokenIgnore;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
/**
|
||||
* 用户Token拦截器
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class UserTokenInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
// 检查是否有 TokenIgnore 注解,有则跳过
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
if (handlerMethod.getMethodAnnotation(TokenIgnore.class) != null ||
|
||||
handlerMethod.getBeanType().getAnnotation(TokenIgnore.class) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
String token = request.getHeader("Authorization");
|
||||
if (StrUtil.isNotEmpty(token)) {
|
||||
try {
|
||||
if (jwtTokenUtil.validateToken(token)) {
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(token);
|
||||
String userId = jwt.getPayload("userId").toString();
|
||||
request.setAttribute("appUserId", userId);
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Logging can be added here if needed
|
||||
log.error("Invalid Token", e);
|
||||
}
|
||||
}
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.getWriter().write("Invalid Token");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.cool.modules.user.token;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* 用户Web配置
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Configuration
|
||||
public class UserWebConfig implements WebMvcConfigurer {
|
||||
final private UserTokenInterceptor userTokenInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(userTokenInterceptor)
|
||||
.addPathPatterns("/app/**");
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,16 @@ package com.cool.modules.user.util;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.plugin.service.CoolPluginService;
|
||||
import com.cool.core.util.CoolPluginInvokers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* UserSmsUtil - 用户短信工具类
|
||||
@@ -23,6 +23,13 @@ import java.util.Map;
|
||||
@Component
|
||||
public class UserSmsUtil {
|
||||
|
||||
/**
|
||||
* 短信发送场景枚举
|
||||
*/
|
||||
public enum SendSceneEnum {
|
||||
login, // 登录
|
||||
}
|
||||
|
||||
private final CoolPluginService coolPluginService;
|
||||
|
||||
private final CoolCache coolCache;
|
||||
@@ -31,13 +38,12 @@ public class UserSmsUtil {
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param phone
|
||||
* @param code
|
||||
*/
|
||||
void sendVerifyCode(String phone, String code) {
|
||||
public void sendVerifyCode(String phone, SendSceneEnum sendSceneEnum) {
|
||||
// 随机生成4位验证码
|
||||
String verifyCode = RandomUtil.randomNumbers(4);
|
||||
send(phone, verifyCode);
|
||||
coolCache.set("sms:" + phone, verifyCode, 60 * 10);
|
||||
coolCache.set(sendSceneEnum.name() + "_sms:" + phone, verifyCode, 60 * 10);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,27 +52,33 @@ public class UserSmsUtil {
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
boolean checkVerifyCode(String phone, String code) {
|
||||
String cacheCode = coolCache.get("sms:" + phone, String.class);
|
||||
return StrUtil.isNotEmpty(code) && code.equals(cacheCode);
|
||||
public void checkVerifyCode(String phone, String code, SendSceneEnum sendSceneEnum) {
|
||||
String key = sendSceneEnum.name() + "_sms:" + phone;
|
||||
String cacheCode = coolCache.get(key, String.class);
|
||||
boolean flag = StrUtil.isNotEmpty(code) && code.equals(cacheCode);
|
||||
if (flag) {
|
||||
// 删除验证码
|
||||
coolCache.del(key);
|
||||
}
|
||||
CoolPreconditions.check(!flag, "验证码错误");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送短信
|
||||
*
|
||||
* @param phone
|
||||
* @param code
|
||||
*/
|
||||
void send(String phone, String code) {
|
||||
public void send(String phone, String code) {
|
||||
List<String> phones = new ArrayList<>();
|
||||
phones.add("xxx");
|
||||
phones.add(phone);
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("code", code);
|
||||
// 插件key sms-tx、sms-ali,哪个实例存在就调用哪个
|
||||
if (coolPluginService.getInstance("sms-tx") != null) {
|
||||
// 调用腾讯短信插件
|
||||
CoolPluginInvokers.invoke("sms-tx", "send", phones, params);
|
||||
} else if (coolPluginService.getInstance("sms-ali") != null) {
|
||||
// 调用阿里短信插件
|
||||
CoolPluginInvokers.invoke("sms-ali", "send", phones, params);
|
||||
|
||||
@@ -64,7 +64,7 @@ spring:
|
||||
useProperties: false
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 1000
|
||||
threadCount: 5
|
||||
threadPriority: 9
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
|
||||
@@ -77,7 +77,6 @@ ignored:
|
||||
- /actuator/**
|
||||
- /download/**
|
||||
- /static/**
|
||||
- /app/**
|
||||
- /favicon.ico
|
||||
- /v3/api-docs/**
|
||||
- /swagger
|
||||
@@ -88,6 +87,11 @@ ignored:
|
||||
- /admin/base/open/**
|
||||
# 忽略记录请求日志url
|
||||
logUrls:
|
||||
- /
|
||||
- /app/**
|
||||
- /css/*
|
||||
- /js/*
|
||||
- /favicon.ico
|
||||
# 文档
|
||||
springdoc:
|
||||
api-docs:
|
||||
|
||||
Reference in New Issue
Block a user