@@ -4,9 +4,11 @@ import cn.hutool.core.util.RandomUtil; | |||||
import lombok.Data; | import lombok.Data; | ||||
import org.springframework.boot.context.properties.ConfigurationProperties; | import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
import java.util.UUID; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
* AuthCodeProperties | |||||
* AuthCodeProps | |||||
* </p> | * </p> | ||||
* | * | ||||
* @author WendyYang | * @author WendyYang | ||||
@@ -14,22 +16,22 @@ import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
*/ | */ | ||||
@Data | @Data | ||||
@ConfigurationProperties(prefix = "auth-code") | @ConfigurationProperties(prefix = "auth-code") | ||||
public class AuthCodeProperties { | |||||
public class AuthCodeProps { | |||||
private String secretKey; | private String secretKey; | ||||
/** | /** | ||||
* authCode失效时间(单位:秒) | * authCode失效时间(单位:秒) | ||||
*/ | */ | ||||
private Integer expireTime = 30; | |||||
private Integer expireTime = 10; | |||||
/** | /** | ||||
* authCode长度(最大:16~32) | |||||
* authCode长度(最大:24~32) | |||||
*/ | */ | ||||
private Integer length = 16; | |||||
private Integer length = 24; | |||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
System.out.println("secretKey:" + RandomUtil.randomString(32)); | |||||
System.out.println("secretKey:" + RandomUtil.randomString(24)); | |||||
} | } | ||||
} | } |
@@ -56,7 +56,6 @@ public class ProjectApprovedReq { | |||||
private Long approvedFileId; | private Long approvedFileId; | ||||
@ApiModelProperty("建设方案文件ID") | @ApiModelProperty("建设方案文件ID") | ||||
@NotNull(message = "建设方案不能为空") | |||||
private Long buildPlanFileId; | private Long buildPlanFileId; | ||||
} | } |
@@ -2,10 +2,9 @@ package com.hz.pm.api.user.controller; | |||||
import com.fasterxml.jackson.databind.ObjectMapper; | import com.fasterxml.jackson.databind.ObjectMapper; | ||||
import com.hz.pm.api.common.config.AuthCodeProperties; | |||||
import com.hz.pm.api.meeting.entity.config.WebProperties; | import com.hz.pm.api.meeting.entity.config.WebProperties; | ||||
import com.hz.pm.api.user.manage.AgentLoginManage; | import com.hz.pm.api.user.manage.AgentLoginManage; | ||||
import com.hz.pm.api.user.manage.AuthCodeManage; | |||||
import com.hz.pm.api.user.manage.AuthCodeLoginManage; | |||||
import com.hz.pm.api.user.model.vo.AuthCodeVO; | import com.hz.pm.api.user.model.vo.AuthCodeVO; | ||||
import com.hz.pm.api.user.util.LoginUserUtil; | import com.hz.pm.api.user.util.LoginUserUtil; | ||||
import com.ningdatech.basic.exception.BizException; | import com.ningdatech.basic.exception.BizException; | ||||
@@ -43,10 +42,10 @@ import java.io.IOException; | |||||
public class UserAuthController { | public class UserAuthController { | ||||
private final ObjectMapper objectMapper; | private final ObjectMapper objectMapper; | ||||
private final AuthCodeManage authCodeManage; | |||||
private final AuthCodeLoginManage authCodeLoginManage; | |||||
private final AgentLoginManage agentLoginManage; | private final AgentLoginManage agentLoginManage; | ||||
private static final String AGENT_LOGIN_PATH = "/api/v1/user/auth/agent-login"; | |||||
private static final String AUTH_CODE_LOGIN_PATH = "/api/v1/user/auth/authCodeLogin"; | |||||
@PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | @PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | ||||
@ApiOperation(value = "登陆") | @ApiOperation(value = "登陆") | ||||
@@ -93,25 +92,25 @@ public class UserAuthController { | |||||
response.getWriter().write(objectMapper.writeValueAsString(BizConst.UNAUTHENTICATED)); | response.getWriter().write(objectMapper.writeValueAsString(BizConst.UNAUTHENTICATED)); | ||||
} | } | ||||
@PostMapping(value = "/proxy/agent-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | |||||
@PostMapping(value = "/proxy/authCodeLogin", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | |||||
@ApiOperation(value = "代登陆") | @ApiOperation(value = "代登陆") | ||||
@WebLog("代登录(代理接口)") | @WebLog("代登录(代理接口)") | ||||
public void agentLoginProxy(@RequestParam(value = "userId") Long userId, | |||||
@RequestParam(value = "username", required = false, defaultValue = "") String username, | |||||
@RequestParam(value = "timestamp") long timestamp, | |||||
@RequestParam(value = "sign") String sign, | |||||
HttpServletRequest request, | |||||
HttpServletResponse response) throws IOException { | |||||
public void proxyAuthCodeLogin(@RequestParam(value = "userId") Long userId, | |||||
@RequestParam(value = "username") String username, | |||||
@RequestParam(value = "timestamp") long timestamp, | |||||
@RequestParam(value = "sign") String sign, | |||||
HttpServletRequest request, | |||||
HttpServletResponse response) throws IOException { | |||||
if (LoginUserUtil.getUserId().equals(userId)) { | if (LoginUserUtil.getUserId().equals(userId)) { | ||||
throw BizException.wrap("代登录用户无效"); | |||||
throw BizException.wrap("代登录用户无效:%s", username); | |||||
} | } | ||||
String targetUserId = String.valueOf(userId); | String targetUserId = String.valueOf(userId); | ||||
if (!agentLoginManage.agentLoginProxySignCheck(targetUserId, timestamp, sign)) { | if (!agentLoginManage.agentLoginProxySignCheck(targetUserId, timestamp, sign)) { | ||||
throw BizException.wrap("签名错误"); | throw BizException.wrap("签名错误"); | ||||
} | } | ||||
String authCode = authCodeManage.generateAuthCode(targetUserId); | |||||
String urlParam = "?userId=" + userId + "&username=" + username + "&authCode=" + authCode; | |||||
String path = WebProperties.apiHost + request.getContextPath() + AGENT_LOGIN_PATH; | |||||
String authCode = authCodeLoginManage.generateAuthCode(targetUserId); | |||||
String urlParam = "?authCode=" + authCode; | |||||
String path = WebProperties.apiHost + request.getContextPath() + AUTH_CODE_LOGIN_PATH; | |||||
response.sendRedirect(path + urlParam); | response.sendRedirect(path + urlParam); | ||||
} | } | ||||
@@ -119,15 +118,14 @@ public class UserAuthController { | |||||
public AuthCodeVO getAuthCode(@RequestParam(value = "userId") String userId, | public AuthCodeVO getAuthCode(@RequestParam(value = "userId") String userId, | ||||
@RequestParam(value = "timestamp") Long timestamp, | @RequestParam(value = "timestamp") Long timestamp, | ||||
@RequestParam(value = "sign") String sign) { | @RequestParam(value = "sign") String sign) { | ||||
String authCode = authCodeManage.generateAuthCode(userId, timestamp, sign); | |||||
String authCode = authCodeLoginManage.generateAuthCode(userId, timestamp, sign); | |||||
return new AuthCodeVO(authCode); | return new AuthCodeVO(authCode); | ||||
} | } | ||||
@GetMapping(value = "/agent-login") | |||||
@ApiOperation(value = "代登陆") | |||||
public void agentLogin(@RequestParam(value = "userId") String userId, | |||||
@RequestParam(value = "username") String username, | |||||
@RequestParam(value = "authCode") String authCode) { | |||||
@GetMapping(value = "/authCodeLogin", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | |||||
@ApiOperation(value = "授权码登录") | |||||
public void authCodeLogin(@RequestParam(value = "authCode") String authCode) { | |||||
// 接口文档使用 | |||||
} | } | ||||
@PostMapping(value = "/mh-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | @PostMapping(value = "/mh-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | ||||
@@ -2,7 +2,6 @@ package com.hz.pm.api.user.manage; | |||||
import cn.hutool.crypto.SecureUtil; | import cn.hutool.crypto.SecureUtil; | ||||
import cn.hutool.crypto.digest.HMac; | import cn.hutool.crypto.digest.HMac; | ||||
import com.hz.pm.api.user.util.LoginUserUtil; | |||||
import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
@@ -3,11 +3,12 @@ package com.hz.pm.api.user.manage; | |||||
import cn.hutool.core.util.RandomUtil; | import cn.hutool.core.util.RandomUtil; | ||||
import cn.hutool.crypto.SecureUtil; | import cn.hutool.crypto.SecureUtil; | ||||
import cn.hutool.crypto.digest.HMac; | import cn.hutool.crypto.digest.HMac; | ||||
import com.hz.pm.api.common.config.AuthCodeProperties; | |||||
import com.hz.pm.api.common.config.AuthCodeProps; | |||||
import com.ningdatech.basic.exception.BizException; | import com.ningdatech.basic.exception.BizException; | ||||
import com.ningdatech.cache.model.cache.CacheKey; | import com.ningdatech.cache.model.cache.CacheKey; | ||||
import com.ningdatech.cache.repository.CachePlusOps; | import com.ningdatech.cache.repository.CachePlusOps; | ||||
import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
@@ -15,32 +16,37 @@ import java.time.Duration; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
* AuthCodeManage | |||||
* AuthCodeLoginManage | |||||
* </p> | * </p> | ||||
* | * | ||||
* @author WendyYang | * @author WendyYang | ||||
* @since 23:59 2023/12/20 | * @since 23:59 2023/12/20 | ||||
*/ | */ | ||||
@Slf4j | |||||
@Component | @Component | ||||
@RequiredArgsConstructor | @RequiredArgsConstructor | ||||
@EnableConfigurationProperties(AuthCodeProperties.class) | |||||
public class AuthCodeManage { | |||||
@EnableConfigurationProperties(AuthCodeProps.class) | |||||
public class AuthCodeLoginManage { | |||||
private final CachePlusOps cachePlusOps; | private final CachePlusOps cachePlusOps; | ||||
private final AuthCodeProperties authCodeProperties; | |||||
private final AuthCodeProps authCodeProps; | |||||
private String generateAuthCode(String userId, boolean checkSign, Long timestamp, String sign) { | private String generateAuthCode(String userId, boolean checkSign, Long timestamp, String sign) { | ||||
if (checkSign) { | if (checkSign) { | ||||
HMac hmacMd5 = SecureUtil.hmacMd5(authCodeProperties.getSecretKey()); | |||||
if (System.currentTimeMillis() - timestamp > 5000) { | |||||
throw BizException.wrap("签名无效"); | |||||
} | |||||
HMac hmacMd5 = SecureUtil.hmacMd5(authCodeProps.getSecretKey()); | |||||
String digestHex = hmacMd5.digestHex(userId + "#" + timestamp); | String digestHex = hmacMd5.digestHex(userId + "#" + timestamp); | ||||
if (!digestHex.equals(sign)) { | if (!digestHex.equals(sign)) { | ||||
throw BizException.wrap("获取授权码失败:签名错误"); | throw BizException.wrap("获取授权码失败:签名错误"); | ||||
} | } | ||||
} | } | ||||
String authCode = RandomUtil.randomString(authCodeProperties.getLength()); | |||||
Duration duration = Duration.ofSeconds(authCodeProperties.getExpireTime()); | |||||
CacheKey key = new CacheKey(userId + "#" + authCode, duration); | |||||
String authCode = RandomUtil.randomString(authCodeProps.getLength()); | |||||
Duration duration = Duration.ofSeconds(authCodeProps.getExpireTime()); | |||||
CacheKey key = new CacheKey(authCode, duration); | |||||
cachePlusOps.set(key, userId); | cachePlusOps.set(key, userId); | ||||
log.info("生成授权码:{} -> {}", userId, authCode); | |||||
return authCode; | return authCode; | ||||
} | } | ||||
@@ -52,9 +58,13 @@ public class AuthCodeManage { | |||||
return generateAuthCode(userId, false, null, null); | return generateAuthCode(userId, false, null, null); | ||||
} | } | ||||
public boolean authCodeCheck(String userId, String authCode) { | |||||
CacheKey key = new CacheKey(userId + "#" + authCode); | |||||
return cachePlusOps.del(key) > 0; | |||||
public String getUserIdByAuthCode(String authCode) { | |||||
CacheKey key = new CacheKey(authCode); | |||||
try { | |||||
return cachePlusOps.get(key); | |||||
} finally { | |||||
cachePlusOps.del(key); | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,81 +0,0 @@ | |||||
package com.hz.pm.api.user.security.auth.agent; | |||||
import com.hz.pm.api.common.util.StrUtils; | |||||
import com.hz.pm.api.user.manage.AuthCodeManage; | |||||
import com.hz.pm.api.user.security.model.WebRequestDetails; | |||||
import com.ningdatech.basic.exception.BizException; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.springframework.http.HttpMethod; | |||||
import org.springframework.security.authentication.AuthenticationServiceException; | |||||
import org.springframework.security.authentication.BadCredentialsException; | |||||
import org.springframework.security.authentication.InternalAuthenticationServiceException; | |||||
import org.springframework.security.core.Authentication; | |||||
import org.springframework.security.core.AuthenticationException; | |||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; | |||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
/** | |||||
* <p> | |||||
* AgentAuthFilter | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 13:25 2023/12/28 | |||||
*/ | |||||
public class AgentAuthFilter extends AbstractAuthenticationProcessingFilter { | |||||
private static final String USER_ID_PARAMETER = "userId"; | |||||
private static final String AUTH_CODE = "authCode"; | |||||
private final AuthCodeManage authCodeManage; | |||||
// =================================================================================================== | |||||
public AgentAuthFilter(String processingUrl,AuthCodeManage authCodeManage) { | |||||
super(new AntPathRequestMatcher(processingUrl, HttpMethod.POST.name())); | |||||
this.authCodeManage = authCodeManage; | |||||
} | |||||
// ======================================================================================================== | |||||
@Override | |||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) | |||||
throws AuthenticationException { | |||||
if (request.getMethod().equals(HttpMethod.POST.name())) { | |||||
throw new AuthenticationServiceException("请求方法错误"); | |||||
} | |||||
String userId = StrUtils.trim(request.getParameter(USER_ID_PARAMETER)); | |||||
if (StringUtils.isBlank(userId)) { | |||||
throw new BadCredentialsException("用户ID不能为空"); | |||||
} | |||||
String authCode = StrUtils.trim(request.getParameter(AUTH_CODE)); | |||||
if (StringUtils.isBlank(userId)) { | |||||
throw new BadCredentialsException("授权码不能为空"); | |||||
} | |||||
if (!authCodeManage.authCodeCheck(userId, authCode)) { | |||||
throw new BadCredentialsException("授权码已过期"); | |||||
} | |||||
try { | |||||
AgentAuthToken authRequest = new AgentAuthToken(userId, userId); | |||||
authRequest.setDetails(new WebRequestDetails(request)); | |||||
return this.getAuthenticationManager().authenticate(authRequest); | |||||
} catch (AuthenticationException e) { | |||||
throw new BadCredentialsException("用户id 不能为空"); | |||||
} catch (BizException e) { | |||||
throw new BadCredentialsException(e.getMessage()); | |||||
} catch (Exception e) { | |||||
throw new InternalAuthenticationServiceException("授权失败:", e); | |||||
} | |||||
} | |||||
private String trim(String trimStr) { | |||||
if (StringUtils.isNotBlank(trimStr)) { | |||||
return trimStr.trim(); | |||||
} | |||||
return null; | |||||
} | |||||
} |
@@ -1,61 +0,0 @@ | |||||
package com.hz.pm.api.user.security.auth.agent; | |||||
import com.hz.pm.api.user.manage.AuthCodeManage; | |||||
import com.hz.pm.api.user.security.config.AuthProperties; | |||||
import org.springframework.beans.factory.annotation.Qualifier; | |||||
import org.springframework.security.authentication.AuthenticationManager; | |||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; | |||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||||
import org.springframework.security.core.userdetails.UserDetailsService; | |||||
import org.springframework.security.web.DefaultSecurityFilterChain; | |||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler; | |||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | |||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* <p> | |||||
* AgentAuthSecurityConfig | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 14:24 2023/12/16 | |||||
*/ | |||||
@Component | |||||
public class AgentAuthSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { | |||||
protected final AuthenticationSuccessHandler defaultLoginSuccessHandler; | |||||
protected final AuthenticationFailureHandler defaultLoginFailureHandler; | |||||
private final UserDetailsService agentLoginUserDetailService; | |||||
private final AuthProperties authProperties; | |||||
private final AuthCodeManage authCodeManage; | |||||
public AgentAuthSecurityConfig(@Qualifier(value = "defaultLoginSuccessHandler") AuthenticationSuccessHandler loginSuccessHandler, | |||||
@Qualifier(value = "defaultLoginFailureHandler") AuthenticationFailureHandler loginFailureHandler, | |||||
@Qualifier(value = "agentLoginUserDetailService") UserDetailsService agentLoginUserDetailService, | |||||
AuthProperties authProperties, | |||||
AuthCodeManage authCodeManage) { | |||||
this.defaultLoginSuccessHandler = loginSuccessHandler; | |||||
this.defaultLoginFailureHandler = loginFailureHandler; | |||||
this.agentLoginUserDetailService = agentLoginUserDetailService; | |||||
this.authProperties = authProperties; | |||||
this.authCodeManage = authCodeManage; | |||||
} | |||||
@Override | |||||
public void configure(HttpSecurity http) { | |||||
AgentAuthFilter agentAuthFilter = new AgentAuthFilter(authProperties.getAgentLoginUrl(), authCodeManage); | |||||
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); | |||||
agentAuthFilter.setAuthenticationManager(authenticationManager); | |||||
agentAuthFilter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler); | |||||
agentAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); | |||||
AgentAuthProvider authenticationProvider = new AgentAuthProvider(); | |||||
authenticationProvider.setUserDetailsService(agentLoginUserDetailService); | |||||
http.authenticationProvider(authenticationProvider) | |||||
.addFilterAfter(agentAuthFilter, UsernamePasswordAuthenticationFilter.class); | |||||
} | |||||
} |
@@ -0,0 +1,60 @@ | |||||
package com.hz.pm.api.user.security.auth.code; | |||||
import cn.hutool.core.util.StrUtil; | |||||
import com.hz.pm.api.common.util.StrUtils; | |||||
import com.hz.pm.api.user.manage.AuthCodeLoginManage; | |||||
import com.hz.pm.api.user.security.model.WebRequestDetails; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.springframework.http.HttpMethod; | |||||
import org.springframework.security.authentication.BadCredentialsException; | |||||
import org.springframework.security.core.Authentication; | |||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; | |||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
/** | |||||
* <p> | |||||
* AuthCodeFilter | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 13:25 2023/12/28 | |||||
*/ | |||||
public class AuthCodeLoginFilter extends AbstractAuthenticationProcessingFilter { | |||||
private static final String AUTH_CODE = "authCode"; | |||||
private final AuthCodeLoginManage authCodeLoginManage; | |||||
// =================================================================================================== | |||||
public AuthCodeLoginFilter(String processingUrl, AuthCodeLoginManage authCodeLoginManage) { | |||||
super(new AntPathRequestMatcher(processingUrl, HttpMethod.GET.name())); | |||||
this.authCodeLoginManage = authCodeLoginManage; | |||||
} | |||||
// ======================================================================================================== | |||||
@Override | |||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { | |||||
String authCode = StrUtils.trim(request.getParameter(AUTH_CODE)); | |||||
if (StringUtils.isBlank(authCode)) { | |||||
throw new BadCredentialsException("授权码不能为空"); | |||||
} | |||||
String userId = authCodeLoginManage.getUserIdByAuthCode(authCode); | |||||
if (StrUtil.isBlank(userId)) { | |||||
throw new BadCredentialsException("授权码无效"); | |||||
} | |||||
try { | |||||
AuthCodeToken authRequest = new AuthCodeToken(userId, userId); | |||||
authRequest.setDetails(new WebRequestDetails(request)); | |||||
return this.getAuthenticationManager().authenticate(authRequest); | |||||
} catch (Exception e) { | |||||
logger.error(e.getMessage(), e); | |||||
throw new BadCredentialsException("授权失败"); | |||||
} | |||||
} | |||||
} |
@@ -1,4 +1,4 @@ | |||||
package com.hz.pm.api.user.security.auth.agent; | |||||
package com.hz.pm.api.user.security.auth.code; | |||||
import lombok.Setter; | import lombok.Setter; | ||||
import org.springframework.security.authentication.AuthenticationProvider; | import org.springframework.security.authentication.AuthenticationProvider; | ||||
@@ -16,23 +16,23 @@ import org.springframework.security.core.userdetails.UserDetailsService; | |||||
* @since 20:41 2023/12/15 | * @since 20:41 2023/12/15 | ||||
*/ | */ | ||||
@Setter | @Setter | ||||
public class AgentAuthProvider implements AuthenticationProvider { | |||||
public class AuthCodeLoginProvider implements AuthenticationProvider { | |||||
private UserDetailsService userDetailsService; | private UserDetailsService userDetailsService; | ||||
@Override | @Override | ||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException { | public Authentication authenticate(Authentication authentication) throws AuthenticationException { | ||||
AgentAuthToken authenticationToken = (AgentAuthToken) authentication; | |||||
AuthCodeToken authenticationToken = (AuthCodeToken) authentication; | |||||
String principal = (String) authenticationToken.getPrincipal(); | String principal = (String) authenticationToken.getPrincipal(); | ||||
UserDetails user = userDetailsService.loadUserByUsername(principal); | UserDetails user = userDetailsService.loadUserByUsername(principal); | ||||
// 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 | // 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 | ||||
return new AgentAuthToken(user, user.getPassword(), user.getAuthorities()); | |||||
return new AuthCodeToken(user, user.getPassword(), user.getAuthorities()); | |||||
} | } | ||||
@Override | @Override | ||||
public boolean supports(Class<?> authentication) { | public boolean supports(Class<?> authentication) { | ||||
return AgentAuthToken.class.isAssignableFrom(authentication); | |||||
return AuthCodeToken.class.isAssignableFrom(authentication); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,61 @@ | |||||
package com.hz.pm.api.user.security.auth.code; | |||||
import com.hz.pm.api.user.manage.AuthCodeLoginManage; | |||||
import com.hz.pm.api.user.security.config.AuthProperties; | |||||
import org.springframework.beans.factory.annotation.Qualifier; | |||||
import org.springframework.security.authentication.AuthenticationManager; | |||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; | |||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||||
import org.springframework.security.core.userdetails.UserDetailsService; | |||||
import org.springframework.security.web.DefaultSecurityFilterChain; | |||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler; | |||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | |||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* <p> | |||||
* AuthCodeSecurityConfig | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 16:02 2024/1/4 | |||||
*/ | |||||
@Component | |||||
public class AuthCodeLoginSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { | |||||
protected final AuthenticationSuccessHandler defaultLoginSuccessHandler; | |||||
protected final AuthenticationFailureHandler defaultLoginFailureHandler; | |||||
private final UserDetailsService userDetailsService; | |||||
private final AuthProperties authProps; | |||||
private final AuthCodeLoginManage authCodeLoginManage; | |||||
public AuthCodeLoginSecurityConfig(@Qualifier(value = "defaultLoginSuccessHandler") AuthenticationSuccessHandler loginSuccessHandler, | |||||
@Qualifier(value = "defaultLoginFailureHandler") AuthenticationFailureHandler loginFailureHandler, | |||||
@Qualifier(value = "authCodeLoginUserDetailService") UserDetailsService userDetailsService, | |||||
AuthProperties authProps, | |||||
AuthCodeLoginManage authCodeLoginManage) { | |||||
this.defaultLoginSuccessHandler = loginSuccessHandler; | |||||
this.defaultLoginFailureHandler = loginFailureHandler; | |||||
this.userDetailsService = userDetailsService; | |||||
this.authProps = authProps; | |||||
this.authCodeLoginManage = authCodeLoginManage; | |||||
} | |||||
@Override | |||||
public void configure(HttpSecurity http) { | |||||
AuthCodeLoginFilter filter = new AuthCodeLoginFilter(authProps.getAuthCodeLoginUrl(), authCodeLoginManage); | |||||
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); | |||||
filter.setAuthenticationManager(authenticationManager); | |||||
filter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler); | |||||
filter.setAuthenticationFailureHandler(defaultLoginFailureHandler); | |||||
AuthCodeLoginProvider authenticationProvider = new AuthCodeLoginProvider(); | |||||
authenticationProvider.setUserDetailsService(userDetailsService); | |||||
http.authenticationProvider(authenticationProvider) | |||||
.addFilterAfter(filter, UsernamePasswordAuthenticationFilter.class); | |||||
} | |||||
} |
@@ -1,9 +1,9 @@ | |||||
package com.hz.pm.api.user.security.auth.agent; | |||||
package com.hz.pm.api.user.security.auth.code; | |||||
import com.hz.pm.api.common.helper.UserInfoHelper; | import com.hz.pm.api.common.helper.UserInfoHelper; | ||||
import com.hz.pm.api.user.model.enumeration.UserAvailableEnum; | |||||
import com.hz.pm.api.user.convert.UserInfoConvertor; | import com.hz.pm.api.user.convert.UserInfoConvertor; | ||||
import com.hz.pm.api.user.model.enumeration.UserAvailableEnum; | |||||
import com.hz.pm.api.user.security.model.UserFullInfoDTO; | import com.hz.pm.api.user.security.model.UserFullInfoDTO; | ||||
import com.hz.pm.api.user.security.model.UserInfoDetails; | import com.hz.pm.api.user.security.model.UserInfoDetails; | ||||
import com.hz.pm.api.user.security.validate.CommonLoginException; | import com.hz.pm.api.user.security.validate.CommonLoginException; | ||||
@@ -15,13 +15,16 @@ import org.springframework.stereotype.Service; | |||||
import java.util.Objects; | import java.util.Objects; | ||||
/** | /** | ||||
* @author LiuXinXin | |||||
* @date 2022/9/30 上午9:49 | |||||
* <p> | |||||
* AuthCodeLoginUserDetailService | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 15:57 2024/1/4 | |||||
*/ | */ | ||||
@Service("agentLoginUserDetailService") | |||||
@Service("authCodeLoginUserDetailService") | |||||
@RequiredArgsConstructor | @RequiredArgsConstructor | ||||
public class AgentLoginUserDetailService implements UserDetailsService { | |||||
public class AuthCodeLoginUserDetailService implements UserDetailsService { | |||||
private final UserInfoHelper userInfoHelper; | private final UserInfoHelper userInfoHelper; | ||||
@@ -1,4 +1,4 @@ | |||||
package com.hz.pm.api.user.security.auth.agent; | |||||
package com.hz.pm.api.user.security.auth.code; | |||||
import org.springframework.security.authentication.AbstractAuthenticationToken; | import org.springframework.security.authentication.AbstractAuthenticationToken; | ||||
import org.springframework.security.core.GrantedAuthority; | import org.springframework.security.core.GrantedAuthority; | ||||
@@ -7,11 +7,14 @@ import org.springframework.security.core.SpringSecurityCoreVersion; | |||||
import java.util.Collection; | import java.util.Collection; | ||||
/** | /** | ||||
* @Author LiuXinXin | |||||
* @Date 2020/8/3 8:52 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
public class AgentAuthToken extends AbstractAuthenticationToken { | |||||
* <p> | |||||
* AuthCodeToken | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 15:45 2024/1/4 | |||||
*/ | |||||
public class AuthCodeToken extends AbstractAuthenticationToken { | |||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | ||||
@@ -24,7 +27,7 @@ public class AgentAuthToken extends AbstractAuthenticationToken { | |||||
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()} will return | * <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()} will return | ||||
* <code>false</code>. | * <code>false</code>. | ||||
*/ | */ | ||||
public AgentAuthToken(String principal, String credentials) { | |||||
public AuthCodeToken(String principal, String credentials) { | |||||
super(null); | super(null); | ||||
this.principal = principal; | this.principal = principal; | ||||
this.credentials = credentials; | this.credentials = credentials; | ||||
@@ -39,12 +42,11 @@ public class AgentAuthToken extends AbstractAuthenticationToken { | |||||
* @param principal | * @param principal | ||||
* @param authorities | * @param authorities | ||||
*/ | */ | ||||
public AgentAuthToken(Object principal, Object credentials, | |||||
Collection<? extends GrantedAuthority> authorities) { | |||||
public AuthCodeToken(Object principal, Object credentials, | |||||
Collection<? extends GrantedAuthority> authorities) { | |||||
super(authorities); | super(authorities); | ||||
this.principal = principal; | this.principal = principal; | ||||
this.credentials = credentials; | this.credentials = credentials; | ||||
// must use super, as we override | |||||
super.setAuthenticated(true); | super.setAuthenticated(true); | ||||
} | } | ||||
@@ -32,7 +32,7 @@ public class AuthProperties { | |||||
/** | /** | ||||
* 代登陆接口 | * 代登陆接口 | ||||
*/ | */ | ||||
private String agentLoginUrl; | |||||
private String authCodeLoginUrl; | |||||
private String mhLoginUrl; | private String mhLoginUrl; | ||||
@@ -1,7 +1,7 @@ | |||||
package com.hz.pm.api.user.security.config; | package com.hz.pm.api.user.security.config; | ||||
import com.hz.pm.api.common.model.constant.CommonConst; | import com.hz.pm.api.common.model.constant.CommonConst; | ||||
import com.hz.pm.api.user.security.auth.agent.AgentAuthSecurityConfig; | |||||
import com.hz.pm.api.user.security.auth.code.AuthCodeLoginSecurityConfig; | |||||
import com.hz.pm.api.user.security.auth.credential.CredentialAuthSecurityConfig; | import com.hz.pm.api.user.security.auth.credential.CredentialAuthSecurityConfig; | ||||
import com.hz.pm.api.user.security.handler.DefaultExpiredSessionStrategy; | import com.hz.pm.api.user.security.handler.DefaultExpiredSessionStrategy; | ||||
import com.hz.pm.api.user.security.handler.DefaultLogoutSuccessHandler; | import com.hz.pm.api.user.security.handler.DefaultLogoutSuccessHandler; | ||||
@@ -31,7 +31,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||||
private final CredentialAuthSecurityConfig credentialAuthSecurityConfig; | private final CredentialAuthSecurityConfig credentialAuthSecurityConfig; | ||||
private final DefaultLogoutSuccessHandler logoutSuccessHandler; | private final DefaultLogoutSuccessHandler logoutSuccessHandler; | ||||
private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; | private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; | ||||
private final AgentAuthSecurityConfig agentAuthSecurityConfig; | |||||
private final AuthCodeLoginSecurityConfig authCodeLoginSecurityConfig; | |||||
private final MhAuthSecurityConfig mhAuthSecurityConfig; | private final MhAuthSecurityConfig mhAuthSecurityConfig; | ||||
@Override | @Override | ||||
@@ -40,7 +40,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||||
http.formLogin() | http.formLogin() | ||||
.loginPage(authProperties.getAuthRequireUrl()) | .loginPage(authProperties.getAuthRequireUrl()) | ||||
.and().apply(credentialAuthSecurityConfig) | .and().apply(credentialAuthSecurityConfig) | ||||
.and().apply(agentAuthSecurityConfig) | |||||
.and().apply(authCodeLoginSecurityConfig) | |||||
.and().apply(mhAuthSecurityConfig) | .and().apply(mhAuthSecurityConfig) | ||||
.and() | .and() | ||||
.authorizeRequests() | .authorizeRequests() | ||||
@@ -3,7 +3,7 @@ security: | |||||
auth-require-url: /api/v1/user/auth/auth-require | auth-require-url: /api/v1/user/auth/auth-require | ||||
invalid-session-url: /api/v1/user/auth/invalid-session | invalid-session-url: /api/v1/user/auth/invalid-session | ||||
password-login-url: /api/v1/user/auth/login | password-login-url: /api/v1/user/auth/login | ||||
agent-login-url: /api/v1/user/auth/agent-login | |||||
auth-code-login-url: /api/v1/user/auth/authCodeLogin | |||||
mh-login-url: /api/v1/user/auth/mh-login | mh-login-url: /api/v1/user/auth/mh-login | ||||
logout-url: /api/v1/user/auth/logout | logout-url: /api/v1/user/auth/logout | ||||
common-login-url: /api/v1/user/auth/common-login | common-login-url: /api/v1/user/auth/common-login | ||||
@@ -3,7 +3,7 @@ security: | |||||
auth-require-url: /api/v1/user/auth/auth-require | auth-require-url: /api/v1/user/auth/auth-require | ||||
invalid-session-url: /api/v1/user/auth/invalid-session | invalid-session-url: /api/v1/user/auth/invalid-session | ||||
password-login-url: /api/v1/user/auth/login | password-login-url: /api/v1/user/auth/login | ||||
agent-login-url: /api/v1/user/auth/agent-login | |||||
auth-code-login-url: /api/v1/user/auth/authCodeLogin | |||||
mh-login-url: /api/v1/user/auth/mh-login | mh-login-url: /api/v1/user/auth/mh-login | ||||
logout-url: /api/v1/user/auth/logout | logout-url: /api/v1/user/auth/logout | ||||
common-login-url: /api/v1/user/auth/common-login | common-login-url: /api/v1/user/auth/common-login | ||||