init
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
68
src/main/java/com/senmesh/security/util/MockUtils.java
Normal file
68
src/main/java/com/senmesh/security/util/MockUtils.java
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
25
src/main/java/com/senmesh/security/util/PasswordUtils.java
Normal file
25
src/main/java/com/senmesh/security/util/PasswordUtils.java
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
146
src/main/java/com/senmesh/security/util/SecurityUtils.java
Normal file
146
src/main/java/com/senmesh/security/util/SecurityUtils.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
51
src/main/java/com/senmesh/security/util/UserLoginUtils.java
Normal file
51
src/main/java/com/senmesh/security/util/UserLoginUtils.java
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user