res = this.checkTokenAndGetUser(request);
- if (res.getOk()) {
- SmartRequestUtil.setUser(res.getData());
+ //放行的Uri前缀
+ String uri = request.getRequestURI();
+ String contextPath = request.getContextPath();
+ String target = uri.replaceFirst(contextPath, "");
+ if (this.contain(this.getIgnoreUrlList(), target)) {
return true;
}
- // 不需要登录
+ //不需要登录
NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class);
+ // 检查是否包含 token
+ String xRequestToken = request.getParameter(RequestHeaderConst.TOKEN);
+ String xHeaderToken = request.getHeader(RequestHeaderConst.TOKEN);
+ String xAccessToken = StringUtils.isNotBlank(xRequestToken) ? xRequestToken : xHeaderToken;
+ // 包含token 则获取用户信息 并保存
+ if (StringUtils.isNotBlank(xAccessToken)) {
+ RequestUser requestUser = userFunction().apply(xAccessToken);
+ if (requestUser != null) {
+ SmartRequestUtil.setRequestUser(requestUser);
+ }
+ // 有token 无需登录
+ if (null != noNeedLogin) {
+ return true;
+ }
+ }
+ // 无token 无需登录
if (null != noNeedLogin) {
return true;
}
- this.outputResult(response, res);
- return false;
+ if (StringUtils.isBlank(xAccessToken)) {
+ this.outputResult(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
+ return false;
+ }
+ return true;
}
- /**
- * 判断 sa-token 未登录场景值
- * 自己根据业务在下面 switch 添加分支判断
- * NotLoginException.NOT_TOKEN 无token
- * NotLoginException.INVALID_TOKEN token无效
- * NotLoginException.TOKEN_TIMEOUT token过期
- * NotLoginException.NO_PREFIX token缺少前缀
- * NotLoginException.KICK_OUT 已被踢下线
- * NotLoginException.TOKEN_FREEZE 已被冻结
- *
- * ps :之所以没有在全局异常里处理 是因为后续还有操作
- */
- public ResponseDTO checkTokenAndGetUser(HttpServletRequest request) {
- /**
- * 处理【非生产环境】的测试 token ,便于开发调试
- * 如不需要 可以删除此段判断代码
- */
- if (SystemEnvEnum.PROD != systemEnv.getCurrentEnv()) {
- String tokenValue = StpUtil.getTokenValue();
- if (NumberUtils.isDigits(tokenValue)) {
- RequestUser user = this.getDevUser(NumberUtils.createLong(tokenValue));
- this.handleRequestIpAndAgent(user, request);
- // sa token 登录身份临时切换
- StpUtil.switchTo(TokenService.generateLoginId(user.getUserId(), user.getUserType()));
- return ResponseDTO.ok(user);
+ public Boolean contain(List ignores, String uri) {
+ if (CollectionUtils.isEmpty(ignores)) {
+ return false;
+ }
+ for (String ignoreUrl : ignores) {
+ if (uri.startsWith(ignoreUrl)) {
+ return true;
}
}
-
- try {
- /**
- * sa-token 会从当前请求 header or body 中获取token
- * 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`
- */
- StpUtil.checkLogin();
- } catch (NotLoginException e) {
- switch (e.getType()) {
- case NotLoginException.BE_REPLACED:
- // token 已被顶下线
- return ResponseDTO.error(UserErrorCode.LOGIN_FROM_OTHER);
- // case NotLoginException.TOKEN_FREEZE:
- // case NotLoginException.KICK_OUT:
- default:
- return ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID);
- }
- }
- // 校验token的用户类型
- UserTypeEnum systemUserTypeEnum = this.getUserType();
- RequestUser user = this.buildCurrentUser(request);
- if (null == user || systemUserTypeEnum != user.getUserType()) {
- return ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID);
- }
- return ResponseDTO.ok(user);
+ return false;
}
/**
@@ -175,40 +136,13 @@ public abstract class AbstractInterceptor implements HandlerInterceptor {
*/
private void outputResult(HttpServletResponse response, ResponseDTO responseDTO) throws IOException {
String msg = JSONObject.toJSONString(responseDTO);
- response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
+ response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(msg);
response.flushBuffer();
}
- /**
- * build 当前请求用户
- *
- * @param request
- * @return
- */
- public RequestUser buildCurrentUser(HttpServletRequest request) {
- // 获取额外数据
- SaSession session = StpUtil.getSession();
- UserTypeEnum userTypeEnum = (UserTypeEnum) session.get(TokenService.EXTRA_KEY_USER_TYPE);
- String userName = session.getString(TokenService.EXTRA_KEY_USER_NAME);
-
- // 当前请求对象
- RequestUser user = new RequestUser();
- user.setUserId(TokenService.getUserId((String) StpUtil.getLoginId()));
- user.setUserName(userName);
- user.setUserType(userTypeEnum);
- this.handleRequestIpAndAgent(user, request);
- return user;
- }
-
- /**
- * 设置 当前请求ip agent
- *
- * @param requestUser
- * @param request
- */
- private void handleRequestIpAndAgent(RequestUser requestUser, HttpServletRequest request) {
- requestUser.setUserAgent(ServletUtil.getHeaderIgnoreCase(request, RequestHeaderConst.USER_AGENT));
- requestUser.setIp(ServletUtil.getClientIP(request));
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+ SmartRequestUtil.remove();
}
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/AbstractSecurityConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/AbstractSecurityConfig.java
new file mode 100644
index 00000000..30fc239b
--- /dev/null
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/AbstractSecurityConfig.java
@@ -0,0 +1,93 @@
+package net.lab1024.sa.common.common.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Spring Security
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2021/8/3 17:50
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室 ( https://1024lab.net )
+ */
+public abstract class AbstractSecurityConfig extends WebSecurityConfigurerAdapter {
+ @Autowired
+ private CorsFilter corsFilter;
+
+ @Autowired
+ private List noNeedLoginUrlList;
+
+ @Autowired
+ private List ignoreUrlList;
+
+ /**
+ * Token获取用户信息
+ *
+ * @return
+ */
+ protected abstract BiFunction userFunction();
+
+ /**
+ * 需要认证的url集合
+ *
+ * @return
+ */
+ protected abstract String[] getAuthenticatedUrlPatterns();
+
+ /**
+ * 不需要登录的url集合
+ *
+ * @return
+ */
+ protected String[] getNoNeedLoginUrl() {
+ return noNeedLoginUrlList.toArray(new String[noNeedLoginUrlList.size()]);
+ }
+
+ /**
+ * 忽略的url集合
+ *
+ * @return
+ */
+ protected String[] getIgnoreUrlList() {
+ return ignoreUrlList.toArray(new String[ignoreUrlList.size()]);
+ }
+
+ @Override
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ httpSecurity
+ // CSRF禁用,因为不使用session
+ .csrf().disable()
+ // 认证失败处理类
+ .exceptionHandling().authenticationEntryPoint(new SecurityAuthenticationFailHandler()).and()
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+ // 过滤请求
+ .authorizeRequests()
+ //忽略的url
+ .antMatchers(this.getIgnoreUrlList()).permitAll()
+ // 不需要登陆的url
+ .antMatchers(this.getNoNeedLoginUrl()).permitAll()
+ //需要校验权限的url
+ .antMatchers(getAuthenticatedUrlPatterns()).authenticated();
+
+ // token filter 进行校验
+ httpSecurity.addFilterBefore(new SecurityTokenFilter(this.userFunction()), UsernamePasswordAuthenticationFilter.class);
+ httpSecurity.addFilterBefore(corsFilter, SecurityTokenFilter.class);
+ // 禁用spring security 使用 X-Frame-Options防止网页被Frame
+ httpSecurity.headers().frameOptions().disable();
+
+ }
+
+
+}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityAuthenticationFailHandler.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityAuthenticationFailHandler.java
new file mode 100644
index 00000000..3e146f18
--- /dev/null
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityAuthenticationFailHandler.java
@@ -0,0 +1,43 @@
+package net.lab1024.sa.common.common.security;
+
+import com.alibaba.fastjson.JSONObject;
+import net.lab1024.sa.common.common.code.ErrorCode;
+import net.lab1024.sa.common.common.code.UserErrorCode;
+import net.lab1024.sa.common.common.domain.ResponseDTO;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 登录认证失败处理
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2022-08-26 20:21:10
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室 ( https://1024lab.net )
+ */
+public class SecurityAuthenticationFailHandler implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
+ this.outputResult(response, UserErrorCode.LOGIN_STATE_INVALID);
+ }
+
+ /**
+ * 输出
+ *
+ * @param response
+ * @param errorCode
+ * @throws IOException
+ */
+ private void outputResult(HttpServletResponse response, ErrorCode errorCode) throws IOException {
+ String msg = JSONObject.toJSONString(ResponseDTO.error(errorCode));
+ response.setContentType("application/json;charset=UTF-8");
+ response.getWriter().write(msg);
+ response.flushBuffer();
+ }
+}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityMethodSource.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityMethodSource.java
new file mode 100644
index 00000000..290b3d9c
--- /dev/null
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityMethodSource.java
@@ -0,0 +1,66 @@
+package net.lab1024.sa.common.common.security;
+
+import net.lab1024.sa.common.common.annoation.SaAuth;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.prepost.PreInvocationAttribute;
+import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
+import org.springframework.security.access.prepost.PrePostInvocationAttributeFactory;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * 此类用于默认给所有接口添加权限 @saAuth.checkPermission('%s')
+ * %s 为类名.方法名
+ * 和使用@PreAuthorize("@saAuth.checkPermission('%s')") 效果一致
+ * 避免所有接口都添加一遍 减轻工作量
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2021-08-30 23:08
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室 ( https://1024lab.net )
+ */
+public class SecurityMethodSource extends PrePostAnnotationSecurityMetadataSource {
+
+
+ private static String EXPRESSION_FORMAT = "@%s.checkPermission('%s')";
+
+ private final PrePostInvocationAttributeFactory attributeFactory;
+
+ private String beanName;
+
+
+ public SecurityMethodSource(PrePostInvocationAttributeFactory attributeFactory, String beanName) {
+ super(attributeFactory);
+ this.attributeFactory = attributeFactory;
+ this.beanName = beanName;
+ }
+
+
+ @Override
+ public Collection getAttributes(Method method, Class> targetClass) {
+ //如果不存在SaAuth采用security认证模式
+ SaAuth saAuth = method.getAnnotation(SaAuth.class);
+ if (saAuth == null) {
+ return super.getAttributes(method, targetClass);
+ }
+
+ //存在添加以URL为权限字符串的校验模式
+ ArrayList configAttributes = new ArrayList(1);
+ String classFullName = targetClass.getName();
+ String methodName = method.getName();
+ String[] classNameArray = StringUtils.split(classFullName, "\\.");
+ String controllerName = classNameArray[classNameArray.length - 1];
+ String privilegeName = controllerName + "." + methodName;
+ String preAuthorizeAttribute = String.format(EXPRESSION_FORMAT, beanName, privilegeName);
+ PreInvocationAttribute pre = this.attributeFactory.createPreInvocationAttribute(null, null, preAuthorizeAttribute);
+ if (pre != null) {
+ configAttributes.add(pre);
+ }
+ return configAttributes;
+ }
+
+}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityPermissionCheckService.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityPermissionCheckService.java
new file mode 100644
index 00000000..29e46559
--- /dev/null
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityPermissionCheckService.java
@@ -0,0 +1,74 @@
+package net.lab1024.sa.common.common.security;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 校验权限
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2022/5/12 21:50
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室 ( https://1024lab.net )
+ */
+public abstract class SecurityPermissionCheckService {
+
+
+ /**
+ * 校验是否有权限
+ *
+ * @param permission
+ * @return
+ */
+ public boolean checkPermission(String permission) {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication == null) {
+ return false;
+ }
+ return checkPermission(authentication, permission);
+ }
+
+ /**
+ * 校验是否有权限
+ *
+ * @param authentication
+ * @param permission
+ * @return
+ */
+ public abstract boolean checkPermission(Authentication authentication, String permission);
+
+ /**
+ * 判断
+ *
+ * @param userDetails
+ * @param permissionStr
+ * @return
+ */
+ protected boolean permissionJudge(UserDetails userDetails, String permissionStr) {
+ if (CollectionUtils.isEmpty(userDetails.getAuthorities())) {
+ return false;
+ }
+
+ if (StringUtils.isBlank(permissionStr)) {
+ return false;
+ }
+
+ String[] permissionArray = permissionStr.split(",");
+ for (String permission : permissionArray) {
+ if(userDetails.getAuthorities().contains(new SimpleGrantedAuthority(permission))){
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityTokenFilter.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityTokenFilter.java
new file mode 100644
index 00000000..1a2ef97e
--- /dev/null
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/security/SecurityTokenFilter.java
@@ -0,0 +1,64 @@
+package net.lab1024.sa.common.common.security;
+
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.common.common.constant.RequestHeaderConst;
+import net.lab1024.sa.common.common.domain.RequestUser;
+import net.lab1024.sa.common.common.util.SmartRequestUtil;
+import org.apache.commons.lang3.StringUtils;
+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.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * 注意此处不能 加入@Component,否则对应ignoreUrl的相关请求 将会进入此Filter,并会覆盖CorsFilter
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2022/5/12 21:50
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室 ( https://1024lab.net )
+ */
+@Slf4j
+public class SecurityTokenFilter extends OncePerRequestFilter {
+
+ private BiFunction userFunction;
+
+ public SecurityTokenFilter(BiFunction userFunction) {
+ this.userFunction = userFunction;
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException {
+ //需要做token校验, 消息头的token优先于请求query参数的token
+ String xHeaderToken = request.getHeader(RequestHeaderConst.TOKEN);
+ String xRequestToken = request.getParameter(RequestHeaderConst.TOKEN);
+ String xAccessToken = null != xHeaderToken ? xHeaderToken : xRequestToken;
+ if (StringUtils.isBlank(xAccessToken)) {
+ chain.doFilter(request, response);
+ return;
+ }
+ //清理spring security
+ SecurityContextHolder.clearContext();
+
+ UserDetails loginUserDetail = userFunction.apply(xAccessToken,request);
+ if (null != loginUserDetail) {
+ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUserDetail, null, loginUserDetail.getAuthorities());
+ authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+ SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+ SmartRequestUtil.setRequestUser((RequestUser) loginUserDetail);
+ }
+ // 若未给予spring security上下文用户授权 则会授权失败 进入AuthenticationEntryPointImpl
+ chain.doFilter(request, response);
+ }
+}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java
index 5e139e25..40210ba2 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/common/util/SmartRequestUtil.java
@@ -1,7 +1,6 @@
package net.lab1024.sa.common.common.util;
-import cn.dev33.satoken.context.SaHolder;
-import cn.dev33.satoken.context.model.SaStorage;
+import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.common.common.domain.RequestUser;
/**
@@ -13,28 +12,26 @@ import net.lab1024.sa.common.common.domain.RequestUser;
* @Email lab1024@163.com
* @Copyright 1024创新实验室 ( https://1024lab.net )
*/
+@Slf4j
public class SmartRequestUtil {
- private static final String STORAGE_KEY = "user";
+ private static final ThreadLocal requestThreadLocal = new ThreadLocal<>();
- public static void setUser(RequestUser user) {
- SaStorage storage = SaHolder.getStorage();
- storage.set(STORAGE_KEY, user);
+ public static void setRequestUser(RequestUser requestUser) {
+ requestThreadLocal.set(requestUser);
}
- /**
- * 获取 当前 token 请求用户
- *
- * @return
- */
- public static RequestUser getUser() {
- SaStorage storage = SaHolder.getStorage();
- return storage.getModel(STORAGE_KEY, RequestUser.class);
+ public static RequestUser getRequestUser() {
+ return requestThreadLocal.get();
}
- public static Long getUserId() {
- RequestUser user = getUser();
- return null != user ? user.getUserId() : null;
+ public static Long getRequestUserId() {
+ RequestUser requestUser = getRequestUser();
+ return null == requestUser ? null : requestUser.getUserId();
+ }
+
+ public static void remove() {
+ requestThreadLocal.remove();
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/DataSourceConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/DataSourceConfig.java
index 3d4b0bd6..cb937a0b 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/DataSourceConfig.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/DataSourceConfig.java
@@ -153,7 +153,7 @@ public class DataSourceConfig {
*
* @return
*/
- @Conditional(SystemEnvConfig.class)
+ @Conditional(SystemEnvironmentConfig.class)
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean<>();
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java
index 494e6f8d..c08339c9 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/MvcConfig.java
@@ -1,19 +1,16 @@
package net.lab1024.sa.common.config;
-import cn.dev33.satoken.interceptor.SaInterceptor;
-import com.google.common.collect.Sets;
import net.lab1024.sa.common.common.interceptor.AbstractInterceptor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
/**
* web相关配置
@@ -28,28 +25,16 @@ import java.util.Set;
public class MvcConfig implements WebMvcConfigurer {
@Autowired(required = false)
- private List interceptorList;
-
- @Autowired(required = false)
- private List saInterceptorList;
+ private List interceptorList;
@Override
- public void addInterceptors(InterceptorRegistry registry) {
- // 先注册 登录拦截器
- Set ignoreUrlSet = Sets.newHashSet();
- if (CollectionUtils.isNotEmpty(interceptorList)) {
- interceptorList.forEach(e -> {
- ignoreUrlSet.addAll(e.getIgnoreUrlList());
- registry.addInterceptor(e).addPathPatterns(e.pathPatterns()).excludePathPatterns(e.getIgnoreUrlList());
- });
- }
-
- // 后注册 sa-token 权限拦截器 不需要可以删除
- if (CollectionUtils.isNotEmpty(saInterceptorList)) {
- saInterceptorList.forEach(i -> {
- registry.addInterceptor(i).addPathPatterns("/**").excludePathPatterns(new ArrayList<>(ignoreUrlSet));
- });
+ public void addInterceptors (InterceptorRegistry registry) {
+ if (CollectionUtils.isEmpty(interceptorList)) {
+ return;
}
+ interceptorList.forEach(e->{
+ registry.addInterceptor(e).addPathPatterns("/**");
+ });
}
@Override
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/RepeatSubmitConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/RepeatSubmitConfig.java
index 9f4083c3..fcfdd5ee 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/RepeatSubmitConfig.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/RepeatSubmitConfig.java
@@ -31,7 +31,7 @@ public class RepeatSubmitConfig {
* @return
*/
private String ticket(String servletPath) {
- Long userId = SmartRequestUtil.getUserId();
+ Long userId = SmartRequestUtil.getRequestUserId();
if (null == userId) {
return StringConst.EMPTY;
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java
index 60cff6a0..901b9246 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SwaggerConfig.java
@@ -57,7 +57,7 @@ import java.util.Map;
@Slf4j
@EnableSwagger2
@Configuration
-@Conditional(SystemEnvConfig.class)
+@Conditional(SystemEnvironmentConfig.class)
public class SwaggerConfig implements EnvironmentAware, BeanDefinitionRegistryPostProcessor {
/**
@@ -198,7 +198,7 @@ public class SwaggerConfig implements EnvironmentAware, BeanDefinitionRegistryPo
Parameter token = new ParameterBuilder().name(RequestHeaderConst.TOKEN)
.description("token")
.modelRef(new ModelRef("string"))
- .parameterType("header").defaultValue("0")
+ .parameterType("header").defaultValue("1")
.required(false)
.build();
return Lists.newArrayList(token);
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SystemEnvConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SystemEnvironmentConfig.java
similarity index 69%
rename from smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SystemEnvConfig.java
rename to smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SystemEnvironmentConfig.java
index bc6b747e..1af9577a 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SystemEnvConfig.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/SystemEnvironmentConfig.java
@@ -1,7 +1,7 @@
package net.lab1024.sa.common.config;
-import net.lab1024.sa.common.common.domain.SystemEnv;
-import net.lab1024.sa.common.common.enumeration.SystemEnvEnum;
+import net.lab1024.sa.common.common.domain.SystemEnvironment;
+import net.lab1024.sa.common.common.enumeration.SystemEnvironmentEnum;
import net.lab1024.sa.common.common.util.SmartEnumUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
@@ -21,7 +21,7 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
* @Copyright 1024创新实验室 ( https://1024lab.net )
*/
@Configuration
-public class SystemEnvConfig implements Condition {
+public class SystemEnvironmentConfig implements Condition {
@Value("${spring.profiles.active}")
private String systemEnvironment;
@@ -32,18 +32,18 @@ public class SystemEnvConfig implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String property = conditionContext.getEnvironment().getProperty("spring.profiles.active");
- return StringUtils.isNotBlank(property) && !SystemEnvEnum.PROD.equalsValue(property);
+ return StringUtils.isNotBlank(property) && !SystemEnvironmentEnum.PROD.equalsValue(property);
}
@Bean
- public SystemEnv initEnvironment() {
- SystemEnvEnum currentEnv = SmartEnumUtil.getEnumByValue(systemEnvironment, SystemEnvEnum.class);
- if (currentEnv == null) {
+ public SystemEnvironment initEnvironment() {
+ SystemEnvironmentEnum currentEnvironment = SmartEnumUtil.getEnumByValue(systemEnvironment, SystemEnvironmentEnum.class);
+ if (currentEnvironment == null) {
throw new ExceptionInInitializerError("无法获取当前环境!请在 application.yaml 配置参数:spring.profiles.active");
}
if (StringUtils.isBlank(projectName)) {
throw new ExceptionInInitializerError("无法获取当前项目名称!请在 application.yaml 配置参数:project.name");
}
- return new SystemEnv(currentEnv == SystemEnvEnum.PROD, projectName, currentEnv);
+ return new SystemEnvironment(currentEnvironment == SystemEnvironmentEnum.PROD, projectName, currentEnvironment);
}
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java
index deea8494..6e8ae116 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/config/UrlConfig.java
@@ -1,11 +1,12 @@
package net.lab1024.sa.common.config;
-import cn.dev33.satoken.annotation.SaIgnore;
+import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.common.common.annoation.NoNeedLogin;
+import net.lab1024.sa.common.common.annoation.SaAuth;
import net.lab1024.sa.common.common.domain.RequestUrlVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,18 +23,21 @@ import java.util.Set;
import java.util.stream.Collectors;
/**
- * description
+ * url配置
*
- * @author Turbolisten
- * @date 2023/7/13 17:42
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2022-05-30 21:22:12
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室 ( https://1024lab.net )
*/
-@Slf4j
@Configuration
+@Slf4j
public class UrlConfig {
-
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
+
/**
* 获取每个方法的请求路径
*
@@ -42,10 +46,11 @@ public class UrlConfig {
@Bean
public Map> methodUrlMap() {
Map> methodUrlMap = Maps.newHashMap();
- // 获取url与类和方法的对应信息
+ //获取url与类和方法的对应信息
Map map = requestMappingHandlerMapping.getHandlerMethods();
for (Map.Entry entry : map.entrySet()) {
RequestMappingInfo requestMappingInfo = entry.getKey();
+
Set urls = requestMappingInfo.getPatternsCondition().getPatterns();
if (CollectionUtils.isEmpty(urls)) {
continue;
@@ -67,20 +72,14 @@ public class UrlConfig {
List authUrlList = Lists.newArrayList();
for (Map.Entry> entry : methodUrlMap.entrySet()) {
Method method = entry.getKey();
- // 忽略权限
- SaIgnore ignore = method.getAnnotation(SaIgnore.class);
- if (null != ignore) {
+ SaAuth saAuth = method.getAnnotation(SaAuth.class);
+ if (null == saAuth) {
continue;
}
- NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class);
- if (null != noNeedLogin) {
- continue;
- }
- Set urlSet = entry.getValue();
- List requestUrlList = this.buildRequestUrl(method, urlSet);
+ List requestUrlList = this.buildRequestUrl(method, entry.getValue());
authUrlList.addAll(requestUrlList);
}
- log.info("需要权限校验的URL:{}", authUrlList.stream().map(RequestUrlVO::getUrl).collect(Collectors.toList()));
+ log.info("需要权限校验的URL:{}", authUrlList.stream().map(e -> e.getUrl()).collect(Collectors.toList()));
return authUrlList;
}
@@ -89,22 +88,29 @@ public class UrlConfig {
if (CollectionUtils.isEmpty(urlSet)) {
return requestUrlList;
}
- // swagger api 说明
+ //url对应的方法名称
+ String className = method.getDeclaringClass().getName();
+ String methodName = method.getName();
+ List list = StrUtil.split(className, ".");
+ String controllerName = list.get(list.size() - 1);
+ String name = controllerName + "." + methodName;
+ //swagger 说明信息
String methodComment = null;
ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
if (apiOperation != null) {
methodComment = apiOperation.value();
}
-
for (String url : urlSet) {
RequestUrlVO requestUrlVO = new RequestUrlVO();
requestUrlVO.setUrl(url);
+ requestUrlVO.setName(name);
requestUrlVO.setComment(methodComment);
requestUrlList.add(requestUrlVO);
}
return requestUrlList;
}
+
/**
* 获取无需登录可以匿名访问的url信息
*
@@ -124,4 +130,21 @@ public class UrlConfig {
log.info("不需要登录的URL:{}", noNeedLoginUrlList);
return noNeedLoginUrlList;
}
-}
+
+ /**
+ * 获取忽略的url信息
+ *
+ * @return
+ */
+ @Bean
+ public List ignoreUrlList() {
+ List ignoreUrlList = Lists.newArrayList();
+ ignoreUrlList.add("/swagger-ui.html");
+ ignoreUrlList.add("/swagger-resources/**");
+ ignoreUrlList.add("/webjars/**");
+ ignoreUrlList.add("/druid/**");
+ ignoreUrlList.add("/*/api-docs");
+ return ignoreUrlList;
+ }
+
+}
\ No newline at end of file
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/handler/GlobalExceptionHandler.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/handler/GlobalExceptionHandler.java
index 3f60effe..66da1df0 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/handler/GlobalExceptionHandler.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/handler/GlobalExceptionHandler.java
@@ -1,16 +1,15 @@
package net.lab1024.sa.common.handler;
-import cn.dev33.satoken.exception.NotPermissionException;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.common.common.code.SystemErrorCode;
import net.lab1024.sa.common.common.code.UserErrorCode;
import net.lab1024.sa.common.common.domain.ResponseDTO;
-import net.lab1024.sa.common.common.domain.SystemEnv;
-import net.lab1024.sa.common.common.enumeration.SystemEnvEnum;
+import net.lab1024.sa.common.common.domain.SystemEnvironment;
import net.lab1024.sa.common.common.exception.BusinessException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
@@ -38,7 +37,7 @@ import java.util.stream.Collectors;
public class GlobalExceptionHandler {
@Autowired
- private SystemEnv systemEnv;
+ private SystemEnvironment systemEnvironment;
/**
* json 格式错误 缺少请求体
@@ -46,7 +45,7 @@ public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler({HttpMessageNotReadableException.class})
public ResponseDTO> jsonFormatExceptionHandler(Exception e) {
- if (!systemEnv.isProd()) {
+ if (!systemEnvironment.isProd()) {
log.error("全局JSON格式错误异常,URL:{}", getCurrentRequestUrl(), e);
}
return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "参数JSON格式错误");
@@ -58,7 +57,7 @@ public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler({TypeMismatchException.class, BindException.class})
public ResponseDTO> paramExceptionHandler(Exception e) {
- if (!systemEnv.isProd()) {
+ if (!systemEnvironment.isProd()) {
log.error("全局参数异常,URL:{}", getCurrentRequestUrl(), e);
}
@@ -78,34 +77,27 @@ public class GlobalExceptionHandler {
return ResponseDTO.error(UserErrorCode.PARAM_ERROR);
}
+ /**
+ * 权限异常
+ */
+ @ResponseBody
+ @ExceptionHandler({AccessDeniedException.class})
+ public ResponseDTO> permissionExceptionHandler(AccessDeniedException e) {
+ return ResponseDTO.error(UserErrorCode.NO_PERMISSION);
+ }
+
/**
* 业务异常
*/
@ResponseBody
@ExceptionHandler(BusinessException.class)
public ResponseDTO> businessExceptionHandler(BusinessException e) {
- if (!systemEnv.isProd()) {
+ if (!systemEnvironment.isProd()) {
log.error("全局业务异常,URL:{}", getCurrentRequestUrl(), e);
}
return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, e.getMessage());
}
- /**
- * sa-token 权限异常处理
- *
- * @param e
- * @return
- */
- @ResponseBody
- @ExceptionHandler(NotPermissionException.class)
- public ResponseDTO permissionException(NotPermissionException e) {
- // 开发环境 方便调试
- if (SystemEnvEnum.PROD != systemEnv.getCurrentEnv()) {
- return ResponseDTO.error(UserErrorCode.NO_PERMISSION, e.getMessage());
- }
- return ResponseDTO.error(UserErrorCode.NO_PERMISSION);
- }
-
/**
* 其他全部异常
*
@@ -116,7 +108,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler(Throwable.class)
public ResponseDTO> errorHandler(Throwable e) {
log.error("捕获全局异常,URL:{}", getCurrentRequestUrl(), e);
- return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, systemEnv.isProd() ? null : e.toString());
+ return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, systemEnvironment.isProd() ? null : e.toString());
}
/**
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/captcha/CaptchaService.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/captcha/CaptchaService.java
index 8911c7c7..36042c67 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/captcha/CaptchaService.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/captcha/CaptchaService.java
@@ -2,9 +2,10 @@ package net.lab1024.sa.common.module.support.captcha;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.common.common.code.UserErrorCode;
import net.lab1024.sa.common.common.constant.StringConst;
import net.lab1024.sa.common.common.domain.ResponseDTO;
-import net.lab1024.sa.common.common.domain.SystemEnv;
+import net.lab1024.sa.common.common.domain.SystemEnvironment;
import net.lab1024.sa.common.common.exception.BusinessException;
import net.lab1024.sa.common.constant.RedisKeyConst;
import net.lab1024.sa.common.module.support.captcha.domain.CaptchaForm;
@@ -42,7 +43,7 @@ public class CaptchaService {
@Autowired
private DefaultKaptcha defaultKaptcha;
@Autowired
- private SystemEnv systemEnvironment;
+ private SystemEnvironment systemEnvironment;
@Autowired
private RedisService redisService;
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/datatracer/service/DataTracerService.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/datatracer/service/DataTracerService.java
index aa05bbc9..2968ed5a 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/datatracer/service/DataTracerService.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/datatracer/service/DataTracerService.java
@@ -157,7 +157,7 @@ public class DataTracerService {
* 保存数据变动记录
*/
public void addTrace(DataTracerForm tracerForm) {
- RequestUser requestUser = SmartRequestUtil.getUser();
+ RequestUser requestUser = SmartRequestUtil.getRequestUser();
this.addTrace(tracerForm, requestUser);
}
@@ -182,7 +182,7 @@ public class DataTracerService {
* 批量保存数据变动记录
*/
public void addTraceList(List tracerFormList) {
- RequestUser requestUser = SmartRequestUtil.getUser();
+ RequestUser requestUser = SmartRequestUtil.getRequestUser();
this.addTraceList(tracerFormList, requestUser);
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/feedback/controller/FeedbackController.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/feedback/controller/FeedbackController.java
index a3242326..b9a1cd09 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/feedback/controller/FeedbackController.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/feedback/controller/FeedbackController.java
@@ -13,6 +13,7 @@ import net.lab1024.sa.common.module.support.feedback.domain.FeedbackAddForm;
import net.lab1024.sa.common.module.support.feedback.domain.FeedbackQueryForm;
import net.lab1024.sa.common.module.support.feedback.domain.FeedbackVO;
import net.lab1024.sa.common.module.support.feedback.service.FeedbackService;
+import net.lab1024.sa.common.module.support.repeatsubmit.annoation.RepeatSubmit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -46,7 +47,7 @@ public class FeedbackController extends SupportBaseController {
@ApiOperation("意见反馈-新增 @author 开云")
@PostMapping("/feedback/add")
public ResponseDTO add(@RequestBody @Valid FeedbackAddForm addForm) {
- RequestUser employee = SmartRequestUtil.getUser();
+ RequestUser employee = SmartRequestUtil.getRequestUser();
return feedbackService.add(addForm, employee);
}
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/file/controller/FileController.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/file/controller/FileController.java
index 4734bfa4..04dc3f10 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/file/controller/FileController.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/file/controller/FileController.java
@@ -5,13 +5,17 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.lab1024.sa.common.common.constant.RequestHeaderConst;
import net.lab1024.sa.common.common.controller.SupportBaseController;
+import net.lab1024.sa.common.common.domain.PageResult;
import net.lab1024.sa.common.common.domain.RequestUser;
import net.lab1024.sa.common.common.domain.ResponseDTO;
import net.lab1024.sa.common.common.util.SmartRequestUtil;
import net.lab1024.sa.common.constant.SwaggerTagConst;
-import net.lab1024.sa.common.module.support.file.constant.FileFolderTypeEnum;
+import net.lab1024.sa.common.module.support.file.domain.form.FileQueryForm;
import net.lab1024.sa.common.module.support.file.domain.form.FileUrlUploadForm;
import net.lab1024.sa.common.module.support.file.domain.vo.FileUploadVO;
+import net.lab1024.sa.common.module.support.file.domain.vo.FileVO;
+import net.lab1024.sa.common.module.support.repeatsubmit.annoation.RepeatSubmit;
+import net.lab1024.sa.common.module.support.file.constant.FileFolderTypeEnum;
import net.lab1024.sa.common.module.support.file.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
@@ -42,14 +46,14 @@ public class FileController extends SupportBaseController {
@PostMapping("/file/upload")
public ResponseDTO upload(@RequestParam MultipartFile file,
@RequestParam Integer folder) {
- RequestUser requestUser = SmartRequestUtil.getUser();
+ RequestUser requestUser = SmartRequestUtil.getRequestUser();
return fileService.fileUpload(file, folder, requestUser);
}
@ApiOperation(value = "文件上传,通过url上传 @author 胡克", notes = FileFolderTypeEnum.INFO)
@PostMapping("/file/upload/url")
public ResponseDTO uploadByUrl(@RequestBody @Valid FileUrlUploadForm uploadForm) {
- RequestUser requestUser = SmartRequestUtil.getUser();
+ RequestUser requestUser = SmartRequestUtil.getRequestUser();
return fileService.fileUpload(uploadForm,requestUser);
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/helpdoc/controller/HelpDocController.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/helpdoc/controller/HelpDocController.java
index 005320e2..cd3eb398 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/helpdoc/controller/HelpDocController.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/helpdoc/controller/HelpDocController.java
@@ -56,7 +56,7 @@ public class HelpDocController extends SupportBaseController {
@RepeatSubmit
public ResponseDTO view(@PathVariable Long helpDocId, HttpServletRequest request) {
return helpDocUserService.view(
- SmartRequestUtil.getUser(),
+ SmartRequestUtil.getRequestUser(),
helpDocId);
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/operatelog/core/OperateLogAspect.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/operatelog/core/OperateLogAspect.java
index 75ef250d..3d9da663 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/operatelog/core/OperateLogAspect.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/operatelog/core/OperateLogAspect.java
@@ -179,7 +179,7 @@ public abstract class OperateLogAspect {
return;
}
//设置用户信息
- RequestUser user = SmartRequestUtil.getUser();
+ RequestUser user = SmartRequestUtil.getRequestUser();
if (user == null) {
return;
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/redis/RedisService.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/redis/RedisService.java
index 3c309499..f99f29ef 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/redis/RedisService.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/redis/RedisService.java
@@ -1,8 +1,8 @@
package net.lab1024.sa.common.module.support.redis;
import com.alibaba.fastjson.JSON;
-import net.lab1024.sa.common.common.domain.SystemEnv;
-import net.lab1024.sa.common.common.enumeration.SystemEnvEnum;
+import net.lab1024.sa.common.common.domain.SystemEnvironment;
+import net.lab1024.sa.common.common.enumeration.SystemEnvironmentEnum;
import net.lab1024.sa.common.common.util.SmartStringUtil;
import net.lab1024.sa.common.constant.RedisKeyConst;
import org.slf4j.Logger;
@@ -52,7 +52,7 @@ public class RedisService {
private SetOperations redisSetOperations;
@Autowired
- private SystemEnv systemEnvironment;
+ private SystemEnvironment systemEnvironment;
/**
@@ -62,7 +62,7 @@ public class RedisService {
* @return
*/
public String generateRedisKey(String prefix, String key) {
- SystemEnvEnum currentEnvironment = systemEnvironment.getCurrentEnv();
+ SystemEnvironmentEnum currentEnvironment = systemEnvironment.getCurrentEnvironment();
return systemEnvironment.getProjectName() + RedisKeyConst.SEPARATOR + currentEnvironment.getValue() + RedisKeyConst.SEPARATOR + prefix + key;
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/table/TableColumnController.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/table/TableColumnController.java
index 0c5ca017..fd657e09 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/table/TableColumnController.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/table/TableColumnController.java
@@ -33,19 +33,19 @@ public class TableColumnController extends SupportBaseController {
@PostMapping("/tableColumn/update")
@RepeatSubmit
public ResponseDTO updateTableColumn(@RequestBody @Valid TableColumnUpdateForm updateForm) {
- return tableColumnService.updateTableColumns(SmartRequestUtil.getUser(), updateForm);
+ return tableColumnService.updateTableColumns(SmartRequestUtil.getRequestUser(), updateForm);
}
@ApiOperation("恢复默认(删除) @author 卓大")
@GetMapping("/tableColumn/delete/{tableId}")
@RepeatSubmit
public ResponseDTO deleteTableColumn(@PathVariable Integer tableId) {
- return tableColumnService.deleteTableColumn(SmartRequestUtil.getUser(), tableId);
+ return tableColumnService.deleteTableColumn(SmartRequestUtil.getRequestUser(), tableId);
}
@ApiOperation("查询表格列 @author 卓大")
@GetMapping("/tableColumn/getColumns/{tableId}")
public ResponseDTO getColumns(@PathVariable Integer tableId) {
- return ResponseDTO.ok(tableColumnService.getTableColumns(SmartRequestUtil.getUser(), tableId));
+ return ResponseDTO.ok(tableColumnService.getTableColumns(SmartRequestUtil.getRequestUser(), tableId));
}
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/LoginDeviceEnum.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/LoginDeviceEnum.java
index 5baa2afa..3fa94198 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/LoginDeviceEnum.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/LoginDeviceEnum.java
@@ -1,7 +1,5 @@
package net.lab1024.sa.common.module.support.token;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
import net.lab1024.sa.common.common.enumeration.BaseEnum;
/**
@@ -13,8 +11,6 @@ import net.lab1024.sa.common.common.enumeration.BaseEnum;
* @Email lab1024@163.com
* @Copyright 1024创新实验室 ( https://1024lab.net )
*/
-@Getter
-@AllArgsConstructor
public enum LoginDeviceEnum implements BaseEnum {
PC(1, "电脑端"),
@@ -25,9 +21,23 @@ public enum LoginDeviceEnum implements BaseEnum {
H5(4, "H5"),
- WX_MP(5, "微信小程序");
+ WEIXIN_MP(5, "微信小程序");
- private final Integer value;
+ LoginDeviceEnum(Integer value, String desc) {
+ this.value = value;
+ this.desc = desc;
+ }
- private final String desc;
+ private Integer value;
+ private String desc;
+
+ @Override
+ public Integer getValue() {
+ return value;
+ }
+
+ @Override
+ public String getDesc() {
+ return desc;
+ }
}
diff --git a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java
index 07b3acea..e3af8649 100644
--- a/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java
+++ b/smart-admin-api/sa-common/src/main/java/net/lab1024/sa/common/module/support/token/TokenService.java
@@ -1,85 +1,220 @@
package net.lab1024.sa.common.module.support.token;
-import cn.dev33.satoken.session.SaSession;
-import cn.dev33.satoken.stp.SaLoginModel;
-import cn.dev33.satoken.stp.StpUtil;
-import net.lab1024.sa.common.common.constant.StringConst;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.common.common.enumeration.UserTypeEnum;
+import net.lab1024.sa.common.constant.RedisKeyConst;
+import net.lab1024.sa.common.module.support.redis.RedisService;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
-import java.util.List;
+import java.util.Date;
+import java.util.Map;
/**
- * 用户token 相关服务
+ * 与用户token的相关的服务
*
- * @author listen
- * @date 2023-07-12 22:48:35
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2021-11-29 19:48:35
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室 ( https://1024lab.net )
*/
@Component
+@Slf4j
public class TokenService {
+ private static final long HOUR_TIME_MILLI = 60 * 60 * 1000;
- public static final String EXTRA_KEY_USER_NAME = "userName";
+ @Value("${token.key}")
+ private String tokenKey;
- public static final String EXTRA_KEY_USER_TYPE = "userType";
+ @Value("${token.expire-day}")
+ private Integer tokenExpire;
+
+ @Autowired
+ private RedisService redisService;
/**
- * 生成Token
+ * 生成Token,并存入redis
*
* @param userId
* @param userName
* @param userTypeEnum
* @param loginDeviceEnum
+ * @param superPasswordFlag 特殊万能密码标识
* @return
*/
- public String generateToken(Long userId,
- String userName,
- UserTypeEnum userTypeEnum,
- LoginDeviceEnum loginDeviceEnum) {
+ public String generateToken(Long userId, String userName, UserTypeEnum userTypeEnum, LoginDeviceEnum loginDeviceEnum, Boolean superPasswordFlag) {
+ long nowTimeMilli = System.currentTimeMillis();
+ Claims jwtClaims = Jwts.claims();
+ jwtClaims.put(JwtConst.CLAIM_ID_KEY, userId);
+ jwtClaims.put(JwtConst.CLAIM_NAME_KEY, userName);
+ jwtClaims.put(JwtConst.CLAIM_USER_TYPE_KEY, userTypeEnum.getValue());
+ jwtClaims.put(JwtConst.CLAIM_DEVICE_KEY, loginDeviceEnum.getValue());
+ jwtClaims.put(JwtConst.CLAIM_SUPER_PASSWORD_FLAG, superPasswordFlag);
+ JwtBuilder jwtBuilder = Jwts.builder()
+ .setClaims(jwtClaims)
+ .setIssuedAt(new Date(nowTimeMilli))
+ .signWith(SignatureAlgorithm.HS512, tokenKey);
- /**
- * 设置登录模式参数
- * 具体参数 {@link SaLoginModel } 属性
- * 已经写的挺清楚的了
- */
- SaLoginModel loginModel = new SaLoginModel();
- // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型
- loginModel.setDevice(String.valueOf(loginDeviceEnum.getDesc()));
+ // 如果是万能密码,则不需要记录到redis中;万能密码最多半个小时有效期
+ if (superPasswordFlag) {
+ jwtBuilder.setExpiration(new Date(nowTimeMilli + (HOUR_TIME_MILLI / 2)));
+ return jwtBuilder.compact();
+ }
- // 登录
- String loginId = generateLoginId(userId, userTypeEnum);
- StpUtil.login(loginId, loginModel);
-
- // 扩展参数 放入会话中 redis session
- SaSession session = StpUtil.getSession();
- session.set(EXTRA_KEY_USER_NAME, userName);
- session.set(EXTRA_KEY_USER_TYPE, userTypeEnum);
- return StpUtil.getTokenValue();
- }
-
- public static String generateLoginId(Long userId, UserTypeEnum userType) {
- return userType.getValue() + StringConst.COLON + userId;
- }
-
- public static Long getUserId(String loginId) {
- return Long.valueOf(loginId.substring(loginId.indexOf(StringConst.COLON) + 1));
- }
-
- public static Integer getUserType(String loginId) {
- return Integer.valueOf(loginId.substring(0, loginId.indexOf(StringConst.COLON)));
+ jwtBuilder.setExpiration(new Date(nowTimeMilli + tokenExpire * 24 * HOUR_TIME_MILLI));
+ String token = jwtBuilder.compact();
+ String redisKey = this.generateTokenRedisKey(userId, userTypeEnum.getValue(), loginDeviceEnum.getValue());
+ redisService.set(redisKey, token, tokenExpire * 24 * 3600);
+ return token;
}
/**
- * 退出登录 注销
+ * 生成登录信息: 含设备信息
+ *
+ * @param userId
+ * @param device
+ * @return
*/
- public void removeToken() {
- StpUtil.logout();
+ private String generateTokenRedisKey(Long userId, Integer userType, Integer device) {
+ String userKey = userType + "_" + userId + "_" + device;
+ return redisService.generateRedisKey(RedisKeyConst.Support.TOKEN, userKey);
}
- public void removeToken(Long userId, UserTypeEnum userType) {
- StpUtil.logout(generateLoginId(userId, userType));
+
+ /**
+ * 强制移除 此用户各端的登录信息
+ *
+ * @param token
+ */
+ public void removeToken(String token) {
+ Map tokenData = this.decryptTokenData(token);
+ if (MapUtils.isEmpty(tokenData)) {
+ return;
+ }
+
+ //特殊账号
+ if (tokenData.get(JwtConst.CLAIM_SUPER_PASSWORD_FLAG) != null) {
+ try {
+ Boolean superPasswordFlag = Boolean.valueOf(tokenData.get(JwtConst.CLAIM_SUPER_PASSWORD_FLAG).toString());
+ if (superPasswordFlag) {
+ return;
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return;
+ }
+ }
+
+ boolean isValid = this.checkRedisToken(tokenData, token);
+ if (!isValid) {
+ return;
+ }
+
+ Long userId = Long.valueOf(tokenData.get(JwtConst.CLAIM_ID_KEY).toString());
+ Integer userType = Integer.valueOf(tokenData.get(JwtConst.CLAIM_USER_TYPE_KEY).toString());
+ Integer device = Integer.valueOf(tokenData.get(JwtConst.CLAIM_DEVICE_KEY).toString());
+
+ String redisKey = this.generateTokenRedisKey(userId, userType, device);
+ redisService.delete(redisKey);
}
- public void removeToken(List userIdList, UserTypeEnum userType) {
- userIdList.forEach(id -> StpUtil.logout(generateLoginId(id, userType)));
+ /**
+ * 解析并校验token信息 获取 userId
+ *
+ * @param token
+ * @return
+ */
+ public Long getUserIdAndValidateToken(String token) {
+ Map parseJwtData = this.decryptTokenData(token);
+ boolean isValid = this.checkRedisToken(parseJwtData, token);
+ if (!isValid) {
+ return null;
+ }
+ Long userId = Long.valueOf(parseJwtData.get(JwtConst.CLAIM_ID_KEY).toString());
+ return userId;
+ }
+
+ /**
+ * 解密和解析token
+ *
+ * @param token
+ * @return
+ */
+ private Map decryptTokenData(String token) {
+ try {
+ return Jwts.parser()
+ .setSigningKey(tokenKey)
+ .parseClaimsJws(token)
+ .getBody();
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ /**
+ * 校验token是否有效
+ *
+ * @param token
+ * @return
+ */
+ private boolean checkRedisToken(Map parseJwtData, String token) {
+ if (MapUtils.isEmpty(parseJwtData)) {
+ return false;
+ }
+ //特殊账号
+ if (parseJwtData.get(JwtConst.CLAIM_SUPER_PASSWORD_FLAG) != null) {
+ try {
+ Boolean superPasswordFlag = Boolean.valueOf(parseJwtData.get(JwtConst.CLAIM_SUPER_PASSWORD_FLAG).toString());
+ if (superPasswordFlag) {
+ return true;
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ Long userId = null;
+ Integer userType = null, device = null;
+
+ if (null != parseJwtData.get(JwtConst.CLAIM_ID_KEY)) {
+ userId = NumberUtils.toLong(parseJwtData.get(JwtConst.CLAIM_ID_KEY).toString(), -1);
+ userId = userId == -1 ? null : userId;
+ }
+
+ if (null != parseJwtData.get(JwtConst.CLAIM_USER_TYPE_KEY)) {
+ userType = NumberUtils.toInt(parseJwtData.get(JwtConst.CLAIM_USER_TYPE_KEY).toString(), -1);
+ userType = userType == -1 ? null : userType;
+ }
+
+ if (null != parseJwtData.get(JwtConst.CLAIM_DEVICE_KEY)) {
+ device = NumberUtils.toInt(parseJwtData.get(JwtConst.CLAIM_DEVICE_KEY).toString(), -1);
+ device = device == -1 ? null : device;
+ }
+
+ if (userId == null || userType == null || device == null) {
+ return false;
+ }
+
+ String redisKey = this.generateTokenRedisKey(userId, userType, device);
+ String redisToken = redisService.get(redisKey);
+ return token.equals(redisToken);
+ }
+
+ /**
+ * 批量移除用户所有设备的token
+ */
+ public void batchRemoveRedisToken(Long userId, UserTypeEnum userTypeEnum) {
+ for (LoginDeviceEnum device : LoginDeviceEnum.values()) {
+ redisService.delete(this.generateTokenRedisKey(userId, userTypeEnum.getValue(), device.getValue()));
+ }
}
}
\ No newline at end of file
diff --git a/smart-admin-api/sa-common/src/main/resources/dev/sa-common.yaml b/smart-admin-api/sa-common/src/main/resources/dev/sa-common.yaml
index 62e609ef..b6b25c9d 100644
--- a/smart-admin-api/sa-common/src/main/resources/dev/sa-common.yaml
+++ b/smart-admin-api/sa-common/src/main/resources/dev/sa-common.yaml
@@ -3,7 +3,7 @@ spring:
datasource:
url: jdbc:p6spy:mysql://127.0.0.1:3306/smart_admin_v2?autoReconnect=true&useServerPreparedStmts=false&rewriteBatchedStatements=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
- password: 123456
+ password: Zhuoda1024lab
initial-size: 2
min-idle: 2
max-active: 10
@@ -27,17 +27,17 @@ spring:
# redis 连接池配置信息
redis:
- database: 12
+ database: 1
host: 127.0.0.1
lettuce:
pool:
- max-active: 50
+ max-active: 5
min-idle: 1
max-idle: 3
max-wait: 30000ms
port: 6379
- timeout: 10s
- password: 123456
+ timeout: 10000ms
+ password:
# 上传文件大小配置
servlet:
@@ -109,6 +109,11 @@ http:
write-timeout: 50000
keep-alive: 300000
+# token相关配置
+token:
+ key: sa-jwt-key
+ expire-day: 7
+
# 跨域配置
access-control-allow-origin: '*'
@@ -118,33 +123,4 @@ heart-beat:
# 热加载配置
reload:
- interval-seconds: 300
-
-############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
-sa-token:
- # token 名称(同时也是 cookie 名称)
- token-name: x-access-token
- # token 前缀 例如:Bear
- token-prefix:
- # jwt秘钥
- # jwt-secret-key: smart-admin
- # token 有效期(单位:秒) 默认30天,-1 代表永久有效
- timeout: 432000
- # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
- active-timeout: -1
- # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
- is-concurrent: false
- # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)(jwt模式下恒false)
- is-share: false
- # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)(jwt模式下无用)
- token-style: simple-uuid
- # 是否打开自动续签 (如果此值为true,框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
- auto-renew: true
- # 是否输出操作日志
- is-log: true
- # 日志等级(trace、debug、info、warn、error、fatal)
- log-level: debug
- # 启动时的字符画打印
- is-print: false
- # 是否从cookie读取token
- is-read-cookie: false
\ No newline at end of file
+ interval-seconds: 300
\ No newline at end of file