1、结构调整

2、抽象工厂优化
This commit is contained in:
2026-03-31 19:35:21 +08:00
parent 87757b352c
commit ebdbdbeb41
667 changed files with 1240 additions and 50173 deletions

View File

@@ -1,8 +1,8 @@
package com.njcn.msgpush.framework.operatelog.config;
import com.njcn.msgpush.framework.operatelog.core.service.LogRecordServiceImpl;
import com.mzt.logapi.service.ILogRecordService;
import com.mzt.logapi.starter.annotation.EnableLogRecord;
import com.njcn.msgpush.framework.operatelog.core.service.LogRecordServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
@@ -11,9 +11,9 @@ import org.springframework.context.annotation.Primary;
/**
* 操作日志配置类
*
* @author HUIHUI
* @author hongawen
*/
@EnableLogRecord(tenant = "admin") // 貌似用不上 tenant 这玩意给个空好啦
@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦
@AutoConfiguration
@Slf4j
public class MsgpushOperateLogConfiguration {

View File

@@ -1,17 +1,16 @@
package com.njcn.msgpush.framework.operatelog.core.service;
import com.mzt.logapi.beans.LogRecord;
import com.mzt.logapi.service.ILogRecordService;
import com.njcn.msgpush.framework.common.biz.system.logger.OperateLogCommonApi;
import com.njcn.msgpush.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO;
import com.njcn.msgpush.framework.common.util.monitor.TracerUtils;
import com.njcn.msgpush.framework.common.util.servlet.ServletUtils;
import com.njcn.msgpush.framework.security.core.LoginUser;
import com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.msgpush.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO;
import com.mzt.logapi.beans.LogRecord;
import com.mzt.logapi.service.ILogRecordService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.List;
@@ -20,7 +19,7 @@ import java.util.List;
*
* 基于 {@link OperateLogCommonApi} 实现,记录操作日志
*
* @author HUIHUI
* @author hongawen
*/
@Slf4j
public class LogRecordServiceImpl implements ILogRecordService {

View File

@@ -2,6 +2,6 @@
* 基于 mzt-log 框架
* 实现操作日志功能
*
* @author HUIHUI
* @author hongawen
*/
package com.njcn.msgpush.framework.operatelog;

View File

@@ -6,7 +6,6 @@ import org.springframework.core.Ordered;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
import org.springframework.stereotype.Component;
/**
* 自定义的 URL 的安全配置

View File

@@ -1,5 +1,6 @@
package com.njcn.msgpush.framework.security.config;
import com.njcn.msgpush.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import com.njcn.msgpush.framework.common.biz.system.permission.PermissionCommonApi;
import com.njcn.msgpush.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
import com.njcn.msgpush.framework.security.core.filter.TokenAuthenticationFilter;
@@ -8,7 +9,6 @@ import com.njcn.msgpush.framework.security.core.handler.AuthenticationEntryPoint
import com.njcn.msgpush.framework.security.core.service.SecurityFrameworkService;
import com.njcn.msgpush.framework.security.core.service.SecurityFrameworkServiceImpl;
import com.njcn.msgpush.framework.web.core.handler.GlobalExceptionHandler;
import com.njcn.msgpush.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@@ -38,7 +38,7 @@ public class MsgpushSecurityAutoConfiguration {
private SecurityProperties securityProperties;
/**
* 身份认证失败处理类 Bean
* 认证失败处理类 Bean
*/
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {

View File

@@ -1,8 +1,8 @@
package com.njcn.msgpush.framework.security.config;
import com.njcn.msgpush.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import com.njcn.msgpush.framework.common.biz.system.permission.PermissionCommonApi;
import com.njcn.msgpush.framework.security.core.rpc.LoginUserRequestInterceptor;
import com.njcn.msgpush.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;

View File

@@ -1,10 +1,10 @@
package com.njcn.msgpush.framework.security.config;
import cn.hutool.core.collection.CollUtil;
import com.njcn.msgpush.framework.security.core.filter.TokenAuthenticationFilter;
import com.njcn.msgpush.framework.web.config.WebProperties;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.njcn.msgpush.framework.security.core.filter.TokenAuthenticationFilter;
import com.njcn.msgpush.framework.web.config.WebProperties;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.DispatcherType;
@@ -114,6 +114,8 @@ public class MsgpushWebSecurityConfigurerAdapter {
.cors(Customizer.withDefaults())
// CSRF 禁用,因为不使用 Session
.csrf(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.formLogin(AbstractHttpConfigurer::disable)
// 基于 token 机制,所以不需要 Session
.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.headers(c -> c.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))

View File

@@ -1,11 +1,11 @@
package com.njcn.msgpush.framework.security.config;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.Collections;
import java.util.List;

View File

@@ -1,7 +1,6 @@
package com.njcn.msgpush.framework.security.core;
import cn.hutool.core.map.MapUtil;
import com.njcn.msgpush.framework.common.enums.UserTypeEnum;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
@@ -10,47 +9,18 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 登录用户信息
*
* @author hongawen
*/
@Data
public class LoginUser {
public static final String INFO_KEY_NICKNAME = "nickname";
public static final String INFO_KEY_DEPT_ID = "deptId";
/**
* 用户编号
*/
private Long id;
/**
* 用户类型
*
* 关联 {@link UserTypeEnum}
*/
private Integer userType;
/**
* 额外的用户信息
*/
private Map<String, String> info;
/**
* 授权范围
*/
private List<String> scopes;
/**
* 过期时间
*/
private LocalDateTime expiresTime;
// ========== 上下文 ==========
/**
* 上下文字段,不进行持久化
*
* 1. 用于基于 LoginUser 维度的临时缓存
*/
@JsonIgnore
private Map<String, Object> context;

View File

@@ -15,7 +15,7 @@ import org.springframework.util.Assert;
public class TransmittableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {
/**
* 使用 TransmittableThreadLocal 实现线程之间上下文的传递。
* 使用 TransmittableThreadLocal 作为上下文
*/
private static final ThreadLocal<SecurityContext> CONTEXT_HOLDER = new TransmittableThreadLocal<>();

View File

@@ -2,7 +2,10 @@ package com.njcn.msgpush.framework.security.core.filter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.msgpush.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import com.njcn.msgpush.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import com.njcn.msgpush.framework.common.exception.ServiceException;
import com.njcn.msgpush.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.njcn.msgpush.framework.common.pojo.CommonResult;
import com.njcn.msgpush.framework.common.util.json.JsonUtils;
import com.njcn.msgpush.framework.common.util.servlet.ServletUtils;
@@ -11,8 +14,6 @@ import com.njcn.msgpush.framework.security.core.LoginUser;
import com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.msgpush.framework.web.core.handler.GlobalExceptionHandler;
import com.njcn.msgpush.framework.web.core.util.WebFrameworkUtils;
import com.njcn.msgpush.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import com.njcn.msgpush.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@@ -26,42 +27,29 @@ import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
/**
* Token 过滤器,验证 token 的有效性
* 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文
*
* @author hongawen
*/
@RequiredArgsConstructor
@Slf4j
public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final SecurityProperties securityProperties;
private final GlobalExceptionHandler globalExceptionHandler;
private final OAuth2TokenCommonApi oauth2TokenApi;
@Override
@SuppressWarnings("NullableProblems")
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
// 情况一,基于 header[login-user] 获得用户,例如说来自 Gateway 或者其它服务透传
LoginUser loginUser = buildLoginUserByHeader(request);
// 情况二,基于 Token 获得用户
// 注意,这里主要满足直接使用 Nginx 直接转发到 Spring Cloud 服务的场景。
if (loginUser == null) {
String token = SecurityFrameworkUtils.obtainAuthorization(request,
securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
if (StrUtil.isNotEmpty(token)) {
Integer userType = WebFrameworkUtils.getLoginUserType(request);
try {
// 1.1 基于 token 构建登录用户
loginUser = buildLoginUserByToken(token, userType);
// 1.2 模拟 Login 功能,方便日常开发调试
if (loginUser == null) {
loginUser = mockLoginUser(request, token, userType);
loginUser = mockLoginUser(token, userType);
}
} catch (Throwable ex) {
CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
@@ -71,57 +59,41 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
}
}
// 设置当前用户
if (loginUser != null) {
SecurityFrameworkUtils.setLoginUser(loginUser, request);
}
// 继续过滤链
chain.doFilter(request, response);
}
private LoginUser buildLoginUserByToken(String token, Integer userType) {
try {
// 校验访问令牌
OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token).getCheckedData();
if (accessToken == null) {
return null;
}
// 用户类型不匹配,无权限
// 注意:只有 /admin-api/* 和 /app-api/* 有 userType才需要比对用户类型
// 类似 WebSocket 的 /ws/* 连接地址,是不需要比对用户类型的
if (userType != null
&& ObjectUtil.notEqual(accessToken.getUserType(), userType)) {
if (userType != null && ObjectUtil.notEqual(accessToken.getUserType(), userType)) {
throw new AccessDeniedException("错误的用户类型");
}
// 构建登录用户
return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
.setInfo(accessToken.getUserInfo()) // 额外的用户信息
return new LoginUser().setId(accessToken.getUserId())
.setUserType(accessToken.getUserType())
.setInfo(accessToken.getUserInfo())
.setScopes(accessToken.getScopes())
.setExpiresTime(accessToken.getExpiresTime());
} catch (ServiceException serviceException) {
// 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可
return null;
if (ObjectUtil.equal(serviceException.getCode(), GlobalErrorCodeConstants.UNAUTHORIZED.getCode())) {
return null;
}
throw serviceException;
}
}
/**
* 模拟登录用户,方便日常开发调试
*
* 注意,在线上环境下,一定要关闭该功能!!!
*
* @param request 请求
* @param token 模拟的 token格式为 {@link SecurityProperties#getMockSecret()} + 用户编号
* @param userType 用户类型
* @return 模拟的 LoginUser
*/
private LoginUser mockLoginUser(HttpServletRequest request, String token, Integer userType) {
private LoginUser mockLoginUser(String token, Integer userType) {
if (!securityProperties.getMockEnable()) {
return null;
}
// 必须以 mockSecret 开头
if (!token.startsWith(securityProperties.getMockSecret())) {
return null;
}
// 构建模拟用户
Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length()));
return new LoginUser().setId(userId).setUserType(userType);
}
@@ -132,20 +104,15 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
return null;
}
try {
loginUserStr = URLDecoder.decode(loginUserStr, StandardCharsets.UTF_8); // 解码,解决中文乱码问题
loginUserStr = URLDecoder.decode(loginUserStr, StandardCharsets.UTF_8);
LoginUser loginUser = JsonUtils.parseObject(loginUserStr, LoginUser.class);
// 用户类型不匹配,无权限
// 注意:只有 /admin-api/* 和 /app-api/* 有 userType才需要比对用户类型
// 类似 WebSocket 的 /ws/* 连接地址,是不需要比对用户类型的
Integer userType = WebFrameworkUtils.getLoginUserType(request);
if (userType != null
&& loginUser != null
&& ObjectUtil.notEqual(loginUser.getUserType(), userType)) {
if (userType != null && loginUser != null && ObjectUtil.notEqual(loginUser.getUserType(), userType)) {
throw new AccessDeniedException("错误的用户类型");
}
return loginUser;
} catch (Exception ex) {
log.error("[buildLoginUserByHeader][解析 LoginUser({}) 发生异常]", loginUserStr, ex); ;
log.error("[buildLoginUserByHeader][parse LoginUser({}) error]", loginUserStr, ex);
throw ex;
}
}

View File

@@ -2,17 +2,17 @@ package com.njcn.msgpush.framework.security.core.handler;
import com.njcn.msgpush.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.njcn.msgpush.framework.common.pojo.CommonResult;
import com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.msgpush.framework.common.util.servlet.ServletUtils;
import com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import static com.njcn.msgpush.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;

View File

@@ -3,15 +3,14 @@ package com.njcn.msgpush.framework.security.core.handler;
import com.njcn.msgpush.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.njcn.msgpush.framework.common.pojo.CommonResult;
import com.njcn.msgpush.framework.common.util.servlet.ServletUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import static com.njcn.msgpush.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
/**
@@ -19,7 +18,7 @@ import static com.njcn.msgpush.framework.common.exception.enums.GlobalErrorCodeC
*
* 补充Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类
*
* @author ruoyi
* @author hongawen
*/
@Slf4j
@SuppressWarnings("JavadocReference") // 忽略文档引用报错

View File

@@ -1,12 +1,12 @@
package com.njcn.msgpush.framework.security.core.service;
import cn.hutool.core.collection.CollUtil;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.njcn.msgpush.framework.common.biz.system.permission.PermissionCommonApi;
import com.njcn.msgpush.framework.common.core.KeyValue;
import com.njcn.msgpush.framework.security.core.LoginUser;
import com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUtils;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
@@ -17,42 +17,27 @@ import java.util.List;
import static com.njcn.msgpush.framework.common.util.cache.CacheUtils.buildCache;
import static com.njcn.msgpush.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
* 默认的 {@link SecurityFrameworkService} 实现类
*
* @author hongawen
*/
@AllArgsConstructor
public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
private final PermissionCommonApi permissionApi;
/**
* 针对 {@link #hasAnyRoles(String...)} 的缓存
*/
private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyRolesCache = buildCache(
Duration.ofMinutes(1L), // 过期时间 1 分钟
Duration.ofMinutes(1L),
new CacheLoader<KeyValue<Long, List<String>>, Boolean>() {
@Override
public Boolean load(KeyValue<Long, List<String>> key) {
return permissionApi.hasAnyRoles(key.getKey(), key.getValue().toArray(new String[0])).getCheckedData();
}
});
/**
* 针对 {@link #hasAnyPermissions(String...)} 的缓存
*/
private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyPermissionsCache = buildCache(
Duration.ofMinutes(1L), // 过期时间 1 分钟
Duration.ofMinutes(1L),
new CacheLoader<KeyValue<Long, List<String>>, Boolean>() {
@Override
public Boolean load(KeyValue<Long, List<String>> key) {
return permissionApi.hasAnyPermissions(key.getKey(), key.getValue().toArray(new String[0])).getCheckedData();
}
});
@Override
@@ -63,7 +48,6 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
@Override
@SneakyThrows
public boolean hasAnyPermissions(String... permissions) {
// 权限校验
Long userId = getLoginUserId();
if (userId == null) {
return false;
@@ -79,7 +63,6 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
@Override
@SneakyThrows
public boolean hasAnyRoles(String... roles) {
// 权限校验
Long userId = getLoginUserId();
if (userId == null) {
return false;
@@ -94,7 +77,6 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
@Override
public boolean hasAnyScopes(String... scope) {
// 权限校验
LoginUser user = SecurityFrameworkUtils.getLoginUser();
if (user == null) {
return false;

View File

@@ -1,10 +1,10 @@
package com.njcn.msgpush.framework.security.core.util;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.msgpush.framework.security.core.LoginUser;
import com.njcn.msgpush.framework.web.core.util.WebFrameworkUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@@ -13,36 +13,16 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Collections;
/**
* 安全服务工具类
*
* @author hongawen
*/
public class SecurityFrameworkUtils {
/**
* HEADER 认证头 value 的前缀
*/
public static final String AUTHORIZATION_BEARER = "Bearer";
public static final String LOGIN_USER_HEADER = "login-user";
private SecurityFrameworkUtils() {}
/**
* 从请求中,获得认证 Token
*
* @param request 请求
* @param headerName 认证 Token 对应的 Header 名字
* @param parameterName 认证 Token 对应的 Parameter 名字
* @return 认证 Token
*/
public static String obtainAuthorization(HttpServletRequest request,
String headerName, String parameterName) {
// 1. 获得 Token。优先级Header > Parameter
public static String obtainAuthorization(HttpServletRequest request, String headerName, String parameterName) {
String token = request.getHeader(headerName);
if (StrUtil.isEmpty(token)) {
token = request.getParameter(parameterName);
@@ -50,16 +30,10 @@ public class SecurityFrameworkUtils {
if (!StringUtils.hasText(token)) {
return null;
}
// 2. 去除 Token 中带的 Bearer
int index = token.indexOf(AUTHORIZATION_BEARER + " ");
return index >= 0 ? token.substring(index + 7).trim() : token;
}
/**
* 获得当前认证信息
*
* @return 认证信息
*/
public static Authentication getAuthentication() {
SecurityContext context = SecurityContextHolder.getContext();
if (context == null) {
@@ -68,11 +42,6 @@ public class SecurityFrameworkUtils {
return context.getAuthentication();
}
/**
* 获取当前用户
*
* @return 当前用户
*/
@Nullable
public static LoginUser getLoginUser() {
Authentication authentication = getAuthentication();
@@ -82,52 +51,28 @@ public class SecurityFrameworkUtils {
return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null;
}
/**
* 获得当前用户的编号,从上下文中
*
* @return 用户编号
*/
@Nullable
public static Long getLoginUserId() {
LoginUser loginUser = getLoginUser();
return loginUser != null ? loginUser.getId() : null;
}
/**
* 获得当前用户的昵称,从上下文中
*
* @return 昵称
*/
@Nullable
public static String getLoginUserNickname() {
LoginUser loginUser = getLoginUser();
return loginUser != null ? MapUtil.getStr(loginUser.getInfo(), LoginUser.INFO_KEY_NICKNAME) : null;
}
/**
* 获得当前用户的部门编号,从上下文中
*
* @return 部门编号
*/
@Nullable
public static Long getLoginUserDeptId() {
LoginUser loginUser = getLoginUser();
return loginUser != null ? MapUtil.getLong(loginUser.getInfo(), LoginUser.INFO_KEY_DEPT_ID) : null;
}
/**
* 设置当前用户
*
* @param loginUser 登录用户
* @param request 请求
*/
public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {
// 创建 Authentication并设置到上下文
Authentication authentication = buildAuthentication(loginUser, request);
SecurityContextHolder.getContext().setAuthentication(authentication);
// 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号;
// 原因是Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
if (request != null) {
WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
@@ -135,12 +80,10 @@ public class SecurityFrameworkUtils {
}
private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {
// 创建 UsernamePasswordAuthenticationToken 对象
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
loginUser, null, Collections.emptyList());
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
return authenticationToken;
}
}

View File

@@ -2,4 +2,4 @@ com.njcn.msgpush.framework.security.config.MsgpushSecurityRpcAutoConfiguration
com.njcn.msgpush.framework.security.config.MsgpushSecurityAutoConfiguration
com.njcn.msgpush.framework.security.config.MsgpushWebSecurityConfigurerAdapter
com.njcn.msgpush.framework.operatelog.config.MsgpushOperateLogConfiguration
com.njcn.msgpush.framework.operatelog.config.MsgpushOperateLogRpcAutoConfiguration
com.njcn.msgpush.framework.operatelog.config.MsgpushOperateLogRpcAutoConfiguration