This commit is contained in:
ran.shang
2025-12-29 16:06:48 +08:00
parent b853edcfde
commit ee95dfa2c2
1600 changed files with 6997 additions and 7445 deletions

View File

@@ -0,0 +1,35 @@
package com.senmesh.security.util;
/**
* request请求host上下文
* @author sr on 2021-08-23
*/
public class HostContextHolder {
private static final ThreadLocal<String> HOST = new ThreadLocal<String>();
/**
*
* @author sr on 2021-08-18
*/
public static void clearHost() {
HOST.remove();
}
/**
* @param host
* @author sr on 2021-08-18
*/
public static void setHost(String host) {
HOST.set(host);
}
/**
* @param host
* @author sr on 2021-08-18
*/
public static String getHost() {
return HOST.get();
}
}

View File

@@ -0,0 +1,68 @@
package com.senmesh.security.util;
import com.senmesh.common.exception.util.Assert;
import com.senmesh.common.util.UserContextHolder;
import com.senmesh.security.dto.SecurityUserDTO;
import com.senmesh.usercenter.constants.OrgConstants;
import com.senmesh.usercenter.constants.UserConstants;
import com.senmesh.usercenter.user.constant.UserTypeEnum;
import com.senmesh.usercenter.user.dto.UserDetailQueryDTO;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* @author sr on 2020-01-05
*/
public class MockUtils {
/**
* 模拟登录机构用户,默认超级管理员/平台机构
*/
public static void mockPlatUser() {
mockUser(UserConstants.SUPERIOR_USER_ID, OrgConstants.PLATFORM_ORG_ID,UserTypeEnum.ORG.getType());
}
/**
* 模拟登录用户
*
* @param userId
* @param orgId(企业用户需要,个人不用可不传)
* @author sr on 2020-09-07
*/
public static void mockUser(Long userId, Long orgId) {
mockUser(userId, orgId, null);
}
/**
* 模拟登录用户(能拿到外部线程登录用户信息,则直接用外部的,不要自己定义固定值)
* 使用mockUser(userId,orgId), 不需要userType,userId已经有用户类型了
* @param userId
* @param orgId 个人用户可为空
* @param userType {@link UserTypeEnum}
* @author sr on 2020-09-07
*/
@Deprecated
public static void mockUser(Long userId, Long orgId,Integer userType) {
Assert.notNull(userId, "无userId,无法mock..");
UserDetailQueryDTO userDetailQueryDto =
UserDetailQueryDTO.builder().userId(userId).orgId(orgId).userType(userType).build();
SecurityUserDTO securityUserDTO = UserLoginUtils.loadUserToMock(userDetailQueryDto);
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken(
securityUserDTO, null));
UserContextHolder.setContext(securityUserDTO);
}
/**
*
* @author sr on 2020-06-17
*/
public static void clearUser() {
SecurityContextHolder.clearContext();
UserContextHolder.clearContext();
}
}

View File

@@ -0,0 +1,25 @@
package com.senmesh.security.util;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class PasswordUtils {
private static PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
private PasswordUtils(PasswordEncoder passwordEncoder) {
PasswordUtils.passwordEncoder = passwordEncoder;
}
public static String encode(String password) {
return passwordEncoder.encode(password);
}
public static boolean match(String password, String encodedPassword) {
return passwordEncoder.matches(password, encodedPassword);
}
}

View File

@@ -0,0 +1,25 @@
package com.senmesh.security.util;
import org.springframework.stereotype.Service;
import com.senmesh.common.service.IMockProvider;
@Service
public class SecurityMockProvider implements IMockProvider{
@Override
public void mockPlatUser() {
MockUtils.mockPlatUser();
}
@Override
public void mockUser(Long userId, Long orgId) {
MockUtils.mockUser(userId, orgId);
}
@Override
public void clearUser() {
MockUtils.clearUser();
}
}

View File

@@ -0,0 +1,119 @@
package com.senmesh.security.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import com.senmesh.common.util.EnvironmentUtils;
import com.senmesh.security.config.SecurityProperties;
import com.senmesh.usercenter.constants.SecurityConstants;
/**
* @author sr on 2020-09-10
*/
public abstract class SecurityPropertyUtils {
private static SecurityProperties securityProperties;
private static List<RequestMatcher> anonRequestMatchers;
private static RequestMatcher unacRequestMatcher = new AntPathRequestMatcher("/unac/**");
private static RequestMatcher authedRequestMatcher = new AntPathRequestMatcher("/authed/**");
public static void setSecurityProperties(SecurityProperties securityProperties) {
SecurityPropertyUtils.securityProperties = securityProperties;
}
public static SecurityProperties getProperties() {
return securityProperties;
}
/**
* 根据匹配路径获取请求匹配对象
*
* @param httpMethod
* @param antPatterns
* @return
* @author sr on 2020-09-10
*/
public static List<RequestMatcher> antMatchers(HttpMethod httpMethod,
String... antPatterns) {
String method = httpMethod == null ? null : httpMethod.toString();
List<RequestMatcher> matchers = new ArrayList<>();
for (String pattern : antPatterns) {
matchers.add(new AntPathRequestMatcher(pattern, method));
}
return matchers;
}
/**
* 获取匿名配置匹配
*
* @return
* @author sr on 2020-09-10
*/
public static List<RequestMatcher> getAnonRequestMatchers() {
if (anonRequestMatchers != null) {
return anonRequestMatchers;
}
String anonymous = EnvironmentUtils.getProperty(SecurityConstants.PROP_KEY_SECURITY_ANONYMOUS);
if (StringUtils.isBlank(anonymous)) {
anonRequestMatchers = Collections.emptyList();
return anonRequestMatchers;
}
anonRequestMatchers = antMatchers(null, anonymous.split(","));
return anonRequestMatchers;
}
/**
* 判断请求是否匿名请求
*
* @param request
* @return
* @author sr on 2020-09-10
*/
public static boolean isAnon(HttpServletRequest request) {
List<RequestMatcher> matchers = getAnonRequestMatchers();
if (matchers.isEmpty()) {
return false;
}
for (RequestMatcher matcher : matchers) {
if (matcher.matches(request)) {
return true;
}
}
return false;
}
/**
* 判断请求是否未激活请求
*
* @param request
* @return
* @author sr on 2021-06-29
*/
public static boolean isUnac(HttpServletRequest request) {
return unacRequestMatcher.matches(request);
}
/**
* 判断请求是否已实名请求
* @param request
* @return
* @author sr on 2021-11-05
*/
public static boolean isAuthed(HttpServletRequest request) {
return authedRequestMatcher.matches(request);
}
}

View File

@@ -0,0 +1,146 @@
package com.senmesh.security.util;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import com.senmesh.common.constant.CommonConstants;
import com.senmesh.common.util.EnvironmentUtils;
import com.senmesh.common.util.RequestUtils;
import com.senmesh.usercenter.constants.SecurityConstants;
import cn.hutool.core.util.URLUtil;
import lombok.extern.slf4j.Slf4j;
/**
* @author sr on 2020-06-15
*/
@Slf4j
public class SecurityUtils {
/** 代理域名 **/
private static final String PROXY_DOMAIN = "proxy.niuyetai.cn";
/** 代理路径请求head-key **/
public static final String PROXY_REQUEST_HEADER_KEY = "X-Proxy-Uri";
public static String encodeURL(String url) {
try {
return URLEncoder.encode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.info("encode失败:{}", e.getMessage());
return null;
}
}
public static String decodeURL(String url) {
try {
if(url.contains("%")) {
return URLDecoder.decode(url, "UTF-8");
}
return url;
} catch (UnsupportedEncodingException e) {
log.info("encode失败:{}", e.getMessage());
return null;
}
}
/**
* 是否本地security调用 ;security.useLocal=false则关闭(调用户中心),其他都本地调用
*
* @return
* @author sr on 2020-06-15
*/
public static boolean useLocal() {
return !CommonConstants.FALSE_STR
.equals(EnvironmentUtils.getProperty(SecurityConstants.PROP_KEY_SECURITY_USELOCAL));
}
/**
* 处理代理路径
* @param request
* @param uri
* @return
* @author sr on 2021-01-16
*/
private static String dealProxy(HttpServletRequest request, String uri) {
String proxyUri = request.getHeader(PROXY_REQUEST_HEADER_KEY);
log.info("proxyUri {}", proxyUri);
// replace域名到代理域名
if (StringUtils.isNotBlank(proxyUri) && uri.contains(PROXY_DOMAIN)) {
return uri.replace(PROXY_DOMAIN, PROXY_DOMAIN + proxyUri);
}
return uri;
}
/**
* 指定成功跳转地址
*
* @param request
* @param redirectUri
* @return
* @author sr on 2021-01-12
*/
public static String dealRedirectUrl(HttpServletRequest request, final String redirectUri) {
String newRedirectUri = redirectUri;
String successToUrl = request.getParameter(SecurityConstants.SUCCESS_TO_URL);
if (StringUtils.isNotBlank(successToUrl)) {
newRedirectUri =
String.format(SecurityConstants.REDIRECT_URL_FORMAT, newRedirectUri,
encodeURL(successToUrl));
}
newRedirectUri = dealProxy(request, newRedirectUri);
log.info("newRedirectUri:{}", newRedirectUri);
return newRedirectUri;
}
public static String dealLoginUrl(HttpServletRequest request, String loginUri) {
String successToUrl = request.getParameter(SecurityConstants.SUCCESS_TO_URL);
// 指定成功跳转,但登陆地址未配置域名
if (StringUtils.isNotBlank(successToUrl)
&& loginUri.indexOf(RequestUtils.DOMAIN_SEPARATOR) < 0) {
String baseUrl = null;
try {
baseUrl = URLUtil.getHost(new URL(successToUrl)).toString();
} catch (MalformedURLException e) {
log.error("successToUrl get domain error:{}", e.getMessage());
return null;
}
loginUri = baseUrl + loginUri;
}
dealProxy(request, loginUri);
return loginUri;
}
public static String dealSuccessUrl(HttpServletRequest request, String successUri, String token) {
if (successUri == null) {
return null;
}
String redirectSuccessToUrl = request.getParameter(SecurityConstants.SUCCESS_TO_URL);
log.debug("redirectSuccessToUrl:{}", redirectSuccessToUrl);
successUri =
StringUtils.isBlank(redirectSuccessToUrl) ? successUri : decodeURL(redirectSuccessToUrl);
if (successUri.indexOf(RequestUtils.DOMAIN_SEPARATOR) > 0) {
String requestBaseUrl = RequestUtils.getHttpDomain(request);
// 成功地址与当前地址域名不一致,跨域,拼接token
if (!successUri.startsWith(requestBaseUrl)) {
if (successUri.indexOf("?") > 0) {
successUri += "&" + SecurityConstants.TOKEN + "=" + token;
} else {
successUri += "?" + SecurityConstants.TOKEN + "=" + token;
}
}
}
dealProxy(request, successUri);
log.info("last redirectSuccessToUrl:{}", successUri);
return successUri;
}
}

View File

@@ -0,0 +1,51 @@
package com.senmesh.security.util;
import org.springframework.stereotype.Component;
import com.senmesh.common.AlitaResult;
import com.senmesh.common.exception.util.Assert;
import com.senmesh.security.dto.SecurityUserDTO;
import com.senmesh.security.mapstruct.UserMapMapper;
import com.senmesh.security.service.IUserSecurityService;
import com.senmesh.usercenter.user.dto.UserDetailQueryDTO;
import com.senmesh.usercenter.user.login.dto.UserDetailDTO;
/**
* @author sr on 2020-06-15
*/
@Component
public class UserLoginUtils {
public static final String SPRING_SECURITY_FORM_ORG_ID_KEY = "orgId";
private static IUserSecurityService userService;
private UserLoginUtils(IUserSecurityService userService) {
UserLoginUtils.userService = userService;
}
/**
* 根据登录信息获取登录对象
*
* @param userCloudService
* @param userService
* @param userDetailQueryDto
* @return
* @author sr on 2020-06-15
*/
public static SecurityUserDTO loadUserToMock(UserDetailQueryDTO userDetailQueryDto) {
AlitaResult<UserDetailDTO> result = null;
result =
userService.findUserDetailDTOResult(userDetailQueryDto);
UserDetailDTO userDetailDTO = result.getData();
Assert.isTrue(result.getSuccess(), "mock失败:" + result.getMsg());
return UserMapMapper.INSTANCE.dtoToDto(userDetailDTO);
}
public static AlitaResult<UserDetailDTO> findUserDetailDTOResult(
UserDetailQueryDTO userDetailQueryDto) {
return userService.findUserDetailDTOResult(userDetailQueryDto);
}
}