@@ -2,7 +2,6 @@ package com.ningdatech.pmapi.common.handler; | |||||
import cn.hutool.json.JSONUtil; | import cn.hutool.json.JSONUtil; | ||||
import com.ningdatech.basic.model.ApiResponse; | import com.ningdatech.basic.model.ApiResponse; | ||||
import com.ningdatech.pmapi.common.util.BizUtils; | |||||
import org.springframework.core.MethodParameter; | import org.springframework.core.MethodParameter; | ||||
import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||
import org.springframework.http.converter.HttpMessageConverter; | import org.springframework.http.converter.HttpMessageConverter; | ||||
@@ -24,7 +23,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; | |||||
"com.ningdatech.pmapi.projectlib.controller", | "com.ningdatech.pmapi.projectlib.controller", | ||||
"com.ningdatech.pmapi.sys.controller", | "com.ningdatech.pmapi.sys.controller", | ||||
"com.ningdatech.pmapi.todocenter.controller", | "com.ningdatech.pmapi.todocenter.controller", | ||||
"com.ningdatech.pmapi.user.controller" | |||||
"com.ningdatech.pmapi.user.controller", | |||||
}) | }) | ||||
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { | public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { | ||||
@@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor; | |||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
import java.time.LocalDateTime; | import java.time.LocalDateTime; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.Map; | import java.util.Map; | ||||
@@ -69,7 +70,7 @@ public class ConstructionPlanManage { | |||||
//首先要判断 项目当前状态 是不是 方案待申报 | //首先要判断 项目当前状态 是不是 方案待申报 | ||||
VUtils.isTrue(!ProjectStatusEnum.PLAN_TO_BE_DECLARED.getCode().equals(projectInfo.getStatus()) || | VUtils.isTrue(!ProjectStatusEnum.PLAN_TO_BE_DECLARED.getCode().equals(projectInfo.getStatus()) || | ||||
!ProjectStatusEnum.NOT_APPROVED.getCode().equals(projectInfo.getStage())) | |||||
!ProjectStatusEnum.NOT_APPROVED.getCode().equals(projectInfo.getStage())) | |||||
.throwMessage("提交失败 该项目不是 待预审状态或者未立项阶段"); | .throwMessage("提交失败 该项目不是 待预审状态或者未立项阶段"); | ||||
//TODO 再判断 该项目是否 真实走完 单位内部审批 | //TODO 再判断 该项目是否 真实走完 单位内部审批 | ||||
@@ -0,0 +1,30 @@ | |||||
package com.ningdatech.pmapi.user.constant; | |||||
import io.swagger.annotations.ApiModel; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/8/17 下午5:55 | |||||
*/ | |||||
@AllArgsConstructor | |||||
@Getter | |||||
@ApiModel("登陆类型") | |||||
public enum LoginTypeEnum { | |||||
/** | |||||
* 浙政钉扫码登陆 | |||||
*/ | |||||
DING_QR_LOGIN, | |||||
/** | |||||
* 手机号验证码登陆 | |||||
*/ | |||||
PHONE_VERIFICATION_CODE_LOGIN, | |||||
/** | |||||
* 账号密码登陆 | |||||
*/ | |||||
USERNAME_PASSWORD_LOGIN; | |||||
} |
@@ -1,20 +0,0 @@ | |||||
package com.ningdatech.pmapi.user.controller; | |||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
import org.springframework.stereotype.Controller; | |||||
/** | |||||
* <p> | |||||
* 前端控制器 | |||||
* </p> | |||||
* | |||||
* @author Lierbao | |||||
* @since 2023-02-01 | |||||
*/ | |||||
@Controller | |||||
@RequestMapping("/pmapi.user/nd-user-auth") | |||||
public class NdUserAuthController { | |||||
} |
@@ -1,20 +0,0 @@ | |||||
package com.ningdatech.pmapi.user.controller; | |||||
import org.springframework.stereotype.Controller; | |||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
/** | |||||
* <p> | |||||
* 前端控制器 | |||||
* </p> | |||||
* | |||||
* @author Lierbao | |||||
* @since 2023-02-01 | |||||
*/ | |||||
@Controller | |||||
@RequestMapping("/pmapi.user/nd-user-info") | |||||
public class NdUserInfoController { | |||||
} |
@@ -36,13 +36,16 @@ public class UserAuthController { | |||||
private final ObjectMapper objectMapper; | private final ObjectMapper objectMapper; | ||||
@PostMapping(value = "/login/password", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | |||||
@PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | |||||
@ApiOperation(value = "账号密码的登陆方式") | @ApiOperation(value = "账号密码的登陆方式") | ||||
@ApiImplicitParams({ | @ApiImplicitParams({ | ||||
@ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "form", dataType = "String"), | |||||
@ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "form", dataType = "String")}) | |||||
@ApiImplicitParam(name = "identifier", value = "用户名", required = true, paramType = "form", dataType = "String"), | |||||
@ApiImplicitParam(name = "credential", value = "凭证", required = true, paramType = "form", dataType = "String"), | |||||
@ApiImplicitParam(name = "loginType", value = "DING_QR_LOGIN 浙政钉扫码登陆,PHONE_VERIFICATION_CODE_LOGIN 手机号验证码登陆" | |||||
, required = true, paramType = "form", dataType = "String")}) | |||||
public void loginByUsernameAndPassword(@RequestParam("username") String username, | public void loginByUsernameAndPassword(@RequestParam("username") String username, | ||||
@RequestParam("password") String password) { | |||||
@RequestParam("credential") String credential, | |||||
@RequestParam("loginType") String loginType) { | |||||
// 不实现任何内容,只是为了出api文档 | // 不实现任何内容,只是为了出api文档 | ||||
} | } | ||||
@@ -18,6 +18,12 @@ public class UserAuthLoginManage { | |||||
private final IUserAuthService iUserAuthService; | private final IUserAuthService iUserAuthService; | ||||
private final IUserInfoService iUserInfoService; | private final IUserInfoService iUserInfoService; | ||||
/** | |||||
* 根据用户名获取 | |||||
* | |||||
* @param username | |||||
* @return | |||||
*/ | |||||
public UserFullInfoDTO queryUserInfoInPasswordAuth(String username) { | public UserFullInfoDTO queryUserInfoInPasswordAuth(String username) { | ||||
UserFullInfoDTO userFullInfoDTO = new UserFullInfoDTO(); | UserFullInfoDTO userFullInfoDTO = new UserFullInfoDTO(); | ||||
userFullInfoDTO.setCompanyId(1L); | userFullInfoDTO.setCompanyId(1L); | ||||
@@ -27,4 +33,37 @@ public class UserAuthLoginManage { | |||||
userFullInfoDTO.setUsername("测试账号"); | userFullInfoDTO.setUsername("测试账号"); | ||||
return userFullInfoDTO; | return userFullInfoDTO; | ||||
} | } | ||||
/** | |||||
* 根据手机号获取 | |||||
* | |||||
* @param phoneNo | |||||
* @return | |||||
*/ | |||||
public UserFullInfoDTO queryUserInfoInPhoneNoAuth(String phoneNo) { | |||||
UserFullInfoDTO userFullInfoDTO = new UserFullInfoDTO(); | |||||
userFullInfoDTO.setCompanyId(1L); | |||||
userFullInfoDTO.setUserId(1L); | |||||
userFullInfoDTO.setIdentifier("123456"); | |||||
userFullInfoDTO.setRealName("测试账号"); | |||||
userFullInfoDTO.setUsername("测试账号"); | |||||
return userFullInfoDTO; | |||||
} | |||||
/** | |||||
* 根据accountId | |||||
* | |||||
* @param accountId | |||||
* @return | |||||
*/ | |||||
public UserFullInfoDTO queryUserInfoInAccountIdAuth(String accountId) { | |||||
UserFullInfoDTO userFullInfoDTO = new UserFullInfoDTO(); | |||||
userFullInfoDTO.setCompanyId(1L); | |||||
userFullInfoDTO.setUserId(1L); | |||||
userFullInfoDTO.setIdentifier("123456"); | |||||
userFullInfoDTO.setRealName("测试账号"); | |||||
userFullInfoDTO.setUsername("测试账号"); | |||||
return userFullInfoDTO; | |||||
} | |||||
} | } |
@@ -1,13 +1,11 @@ | |||||
package com.ningdatech.pmapi.user.security.auth; | package com.ningdatech.pmapi.user.security.auth; | ||||
import com.google.common.collect.Lists; | |||||
import com.ningdatech.basic.util.CollUtils; | |||||
import com.ningdatech.basic.util.NdJsonUtil; | import com.ningdatech.basic.util.NdJsonUtil; | ||||
import com.ningdatech.basic.util.StrPool; | import com.ningdatech.basic.util.StrPool; | ||||
import com.ningdatech.pmapi.common.constant.BizConst; | import com.ningdatech.pmapi.common.constant.BizConst; | ||||
import com.ningdatech.pmapi.common.constant.CommonConstant; | import com.ningdatech.pmapi.common.constant.CommonConstant; | ||||
import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy; | import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy; | ||||
import com.ningdatech.pmapi.user.security.auth.password.UsernamePasswordAuthSecurityConfig; | |||||
import com.ningdatech.pmapi.user.security.auth.credential.CredentialAuthSecurityConfig; | |||||
import org.springframework.beans.factory.annotation.Qualifier; | import org.springframework.beans.factory.annotation.Qualifier; | ||||
import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||
import org.springframework.http.HttpStatus; | import org.springframework.http.HttpStatus; | ||||
@@ -18,7 +16,6 @@ import org.springframework.security.web.authentication.logout.LogoutSuccessHandl | |||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository; | import org.springframework.security.web.csrf.CookieCsrfTokenRepository; | ||||
import java.io.PrintWriter; | import java.io.PrintWriter; | ||||
import java.util.ArrayList; | |||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.Set; | import java.util.Set; | ||||
@@ -31,16 +28,16 @@ import java.util.Set; | |||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||||
private final AuthProperties authProperties; | private final AuthProperties authProperties; | ||||
private final UsernamePasswordAuthSecurityConfig usernamePasswordAuthSecurityConfig; | |||||
private final CredentialAuthSecurityConfig credentialAuthSecurityConfig; | |||||
private final LogoutSuccessHandler logoutSuccessHandler; | private final LogoutSuccessHandler logoutSuccessHandler; | ||||
private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; | private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; | ||||
public WebSecurityConfig(AuthProperties authProperties, | public WebSecurityConfig(AuthProperties authProperties, | ||||
UsernamePasswordAuthSecurityConfig usernamePasswordAuthSecurityConfig, | |||||
CredentialAuthSecurityConfig credentialAuthSecurityConfig, | |||||
@Qualifier(value = "defaultLogoutSuccessHandler") LogoutSuccessHandler logoutSuccessHandler, | @Qualifier(value = "defaultLogoutSuccessHandler") LogoutSuccessHandler logoutSuccessHandler, | ||||
DefaultExpiredSessionStrategy defaultExpiredSessionStrategy) { | DefaultExpiredSessionStrategy defaultExpiredSessionStrategy) { | ||||
this.authProperties = authProperties; | this.authProperties = authProperties; | ||||
this.usernamePasswordAuthSecurityConfig = usernamePasswordAuthSecurityConfig; | |||||
this.credentialAuthSecurityConfig = credentialAuthSecurityConfig; | |||||
this.logoutSuccessHandler = logoutSuccessHandler; | this.logoutSuccessHandler = logoutSuccessHandler; | ||||
this.defaultExpiredSessionStrategy = defaultExpiredSessionStrategy; | this.defaultExpiredSessionStrategy = defaultExpiredSessionStrategy; | ||||
} | } | ||||
@@ -50,7 +47,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||||
assemblerPreAuthUrls(http); | assemblerPreAuthUrls(http); | ||||
http.formLogin() | http.formLogin() | ||||
.loginPage(authProperties.getAuthRequireUrl()) | .loginPage(authProperties.getAuthRequireUrl()) | ||||
.and().apply(usernamePasswordAuthSecurityConfig) | |||||
.and().apply(credentialAuthSecurityConfig) | |||||
.and() | .and() | ||||
.authorizeRequests().antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll().anyRequest() | .authorizeRequests().antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll().anyRequest() | ||||
.authenticated().and() | .authenticated().and() | ||||
@@ -0,0 +1,42 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.credential; | |||||
import com.ningdatech.pmapi.user.manage.UserAuthLoginManage; | |||||
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||||
import lombok.RequiredArgsConstructor; | |||||
import org.springframework.security.core.userdetails.UserDetailsService; | |||||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||||
import org.springframework.stereotype.Service; | |||||
import java.util.Objects; | |||||
/** | |||||
* @author LiuXinXin | |||||
* @date 2022/9/30 上午9:49 | |||||
*/ | |||||
@Service("accountIdLoginUserDetailService") | |||||
@RequiredArgsConstructor | |||||
public class AccountIdLoginUserDetailService implements UserDetailsService { | |||||
private final UserAuthLoginManage userAuthLoginManage; | |||||
@Override | |||||
public UserInfoDetails loadUserByUsername(String accountId) throws UsernameNotFoundException { | |||||
UserFullInfoDTO userFullInfoDTO = userAuthLoginManage.queryUserInfoInAccountIdAuth(accountId); | |||||
if (Objects.isNull(userFullInfoDTO)) { | |||||
throw new UsernameNotFoundException(String.format("%s user not exist", accountId)); | |||||
} | |||||
UserInfoDetails userInfoDetails = new UserInfoDetails(); | |||||
userInfoDetails.setUserId(userFullInfoDTO.getUserId()); | |||||
userInfoDetails.setUsername(userFullInfoDTO.getUsername()); | |||||
userInfoDetails.setRealName(userFullInfoDTO.getRealName()); | |||||
userInfoDetails.setRole(userFullInfoDTO.getRole()); | |||||
userInfoDetails.setRegionCode(userFullInfoDTO.getRegionCode()); | |||||
userInfoDetails.setCompanyId(userFullInfoDTO.getCompanyId()); | |||||
userInfoDetails.setIdentifier(userFullInfoDTO.getIdentifier()); | |||||
userInfoDetails.setPassword(userFullInfoDTO.getCredential()); | |||||
return userInfoDetails; | |||||
} | |||||
} |
@@ -1,6 +1,7 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
package com.ningdatech.pmapi.user.security.auth.credential; | |||||
import com.ningdatech.pmapi.user.security.auth.AuthProperties; | import com.ningdatech.pmapi.user.security.auth.AuthProperties; | ||||
import com.ningdatech.zwdd.client.ZwddAuthClient; | |||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.beans.factory.annotation.Qualifier; | import org.springframework.beans.factory.annotation.Qualifier; | ||||
import org.springframework.security.authentication.AuthenticationManager; | import org.springframework.security.authentication.AuthenticationManager; | ||||
@@ -18,7 +19,7 @@ import org.springframework.stereotype.Component; | |||||
* 账号密码登陆的认证配置 | * 账号密码登陆的认证配置 | ||||
*/ | */ | ||||
@Component | @Component | ||||
public class UsernamePasswordAuthSecurityConfig | |||||
public class CredentialAuthSecurityConfig | |||||
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { | extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { | ||||
@Autowired | @Autowired | ||||
@@ -30,8 +31,8 @@ public class UsernamePasswordAuthSecurityConfig | |||||
protected AuthenticationFailureHandler defaultLoginFailureHandler; | protected AuthenticationFailureHandler defaultLoginFailureHandler; | ||||
@Autowired | @Autowired | ||||
@Qualifier(value = "passwordLoginUserDetailService") | |||||
private UserDetailsService passwordLoginUserDetailService; | |||||
@Qualifier(value = "credentialLoginUserDetailService") | |||||
private UserDetailsService credentialLoginUserDetailService; | |||||
@Autowired | @Autowired | ||||
private PasswordEncoder passwordEncoder; | private PasswordEncoder passwordEncoder; | ||||
@@ -41,6 +42,9 @@ public class UsernamePasswordAuthSecurityConfig | |||||
private AuthenticationManager authenticationManager; | private AuthenticationManager authenticationManager; | ||||
@Autowired | |||||
private ZwddAuthClient zwddAuthClient; | |||||
@Override | @Override | ||||
public void configure(HttpSecurity http) throws Exception { | public void configure(HttpSecurity http) throws Exception { | ||||
UsernamePasswordAuthFilter usernamePasswordAuthFilter = | UsernamePasswordAuthFilter usernamePasswordAuthFilter = | ||||
@@ -51,9 +55,12 @@ public class UsernamePasswordAuthSecurityConfig | |||||
usernamePasswordAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); | usernamePasswordAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); | ||||
UsernamePasswordAuthProvider authenticationProvider = new UsernamePasswordAuthProvider(); | UsernamePasswordAuthProvider authenticationProvider = new UsernamePasswordAuthProvider(); | ||||
authenticationProvider.setUserDetailsService(passwordLoginUserDetailService); | |||||
authenticationProvider.setUserDetailsService(credentialLoginUserDetailService); | |||||
// 确保对密码进行加密的encoder和解密的encoder相同 | // 确保对密码进行加密的encoder和解密的encoder相同 | ||||
authenticationProvider.setPasswordEncoder(passwordEncoder); | authenticationProvider.setPasswordEncoder(passwordEncoder); | ||||
// 传入浙政钉client | |||||
authenticationProvider.setZwddAuthClient(zwddAuthClient); | |||||
http.authenticationProvider(authenticationProvider).addFilterAfter(usernamePasswordAuthFilter, | http.authenticationProvider(authenticationProvider).addFilterAfter(usernamePasswordAuthFilter, | ||||
UsernamePasswordAuthenticationFilter.class); | UsernamePasswordAuthenticationFilter.class); | ||||
} | } |
@@ -1,5 +1,6 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
package com.ningdatech.pmapi.user.security.auth.credential; | |||||
import com.ningdatech.pmapi.user.constant.LoginTypeEnum; | |||||
import org.springframework.security.authentication.AbstractAuthenticationToken; | import org.springframework.security.authentication.AbstractAuthenticationToken; | ||||
import org.springframework.security.core.GrantedAuthority; | import org.springframework.security.core.GrantedAuthority; | ||||
import org.springframework.security.core.SpringSecurityCoreVersion; | import org.springframework.security.core.SpringSecurityCoreVersion; | ||||
@@ -11,7 +12,7 @@ import java.util.Collection; | |||||
* @Date 2020/8/3 8:52 下午 | * @Date 2020/8/3 8:52 下午 | ||||
* @Version 1.0 | * @Version 1.0 | ||||
**/ | **/ | ||||
public class UsernamePasswordAuthToken extends AbstractAuthenticationToken { | |||||
public class CredentialAuthToken extends AbstractAuthenticationToken { | |||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | ||||
@@ -19,16 +20,18 @@ public class UsernamePasswordAuthToken extends AbstractAuthenticationToken { | |||||
private final Object credentials; | private final Object credentials; | ||||
private final LoginTypeEnum loginTypeEnum; | |||||
/** | /** | ||||
* This constructor can be safely used by any code that wishes to create a | * This constructor can be safely used by any code that wishes to create a | ||||
* <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 UsernamePasswordAuthToken(String principal, String credentials) { | |||||
public CredentialAuthToken(String principal, String credentials, String loginTypeEnum) { | |||||
super(null); | super(null); | ||||
this.principal = principal; | this.principal = principal; | ||||
this.credentials = credentials; | this.credentials = credentials; | ||||
this.loginTypeEnum = LoginTypeEnum.valueOf(loginTypeEnum); | |||||
setAuthenticated(false); | setAuthenticated(false); | ||||
} | } | ||||
@@ -40,15 +43,20 @@ public class UsernamePasswordAuthToken extends AbstractAuthenticationToken { | |||||
* @param principal | * @param principal | ||||
* @param authorities | * @param authorities | ||||
*/ | */ | ||||
public UsernamePasswordAuthToken(Object principal, Object credentials, | |||||
Collection<? extends GrantedAuthority> authorities) { | |||||
public CredentialAuthToken(Object principal, Object credentials, | |||||
Collection<? extends GrantedAuthority> authorities) { | |||||
super(authorities); | super(authorities); | ||||
this.principal = principal; | this.principal = principal; | ||||
this.credentials = credentials; | this.credentials = credentials; | ||||
this.loginTypeEnum = null; | |||||
// must use super, as we override | // must use super, as we override | ||||
super.setAuthenticated(true); | super.setAuthenticated(true); | ||||
} | } | ||||
public LoginTypeEnum getLoginTypeEnum() { | |||||
return this.loginTypeEnum; | |||||
} | |||||
@Override | @Override | ||||
public Object getCredentials() { | public Object getCredentials() { | ||||
return this.credentials; | return this.credentials; |
@@ -1,4 +1,4 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
package com.ningdatech.pmapi.user.security.auth.credential; | |||||
import com.ningdatech.pmapi.user.manage.UserAuthLoginManage; | import com.ningdatech.pmapi.user.manage.UserAuthLoginManage; | ||||
@@ -16,9 +16,9 @@ import java.util.Objects; | |||||
* @date 2022/9/30 上午9:49 | * @date 2022/9/30 上午9:49 | ||||
*/ | */ | ||||
@Service("passwordLoginUserDetailService") | |||||
@Service("credentialLoginUserDetailService") | |||||
@RequiredArgsConstructor | @RequiredArgsConstructor | ||||
public class PasswordLoginUserDetailService implements UserDetailsService { | |||||
public class CredentialLoginUserDetailService implements UserDetailsService { | |||||
private final UserAuthLoginManage userAuthLoginManage; | private final UserAuthLoginManage userAuthLoginManage; | ||||
@@ -0,0 +1,42 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.credential; | |||||
import com.ningdatech.pmapi.user.manage.UserAuthLoginManage; | |||||
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||||
import lombok.RequiredArgsConstructor; | |||||
import org.springframework.security.core.userdetails.UserDetailsService; | |||||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||||
import org.springframework.stereotype.Service; | |||||
import java.util.Objects; | |||||
/** | |||||
* @author LiuXinXin | |||||
* @date 2022/9/30 上午9:49 | |||||
*/ | |||||
@Service("phoneNoLoginUserDetailService") | |||||
@RequiredArgsConstructor | |||||
public class PhoneNoLoginUserDetailService implements UserDetailsService { | |||||
private final UserAuthLoginManage userAuthLoginManage; | |||||
@Override | |||||
public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |||||
UserFullInfoDTO userFullInfoDTO = userAuthLoginManage.queryUserInfoInPhoneNoAuth(username); | |||||
if (Objects.isNull(userFullInfoDTO)) { | |||||
throw new UsernameNotFoundException(String.format("%s user not exist", username)); | |||||
} | |||||
UserInfoDetails userInfoDetails = new UserInfoDetails(); | |||||
userInfoDetails.setUserId(userFullInfoDTO.getUserId()); | |||||
userInfoDetails.setUsername(userFullInfoDTO.getUsername()); | |||||
userInfoDetails.setRealName(userFullInfoDTO.getRealName()); | |||||
userInfoDetails.setRole(userFullInfoDTO.getRole()); | |||||
userInfoDetails.setRegionCode(userFullInfoDTO.getRegionCode()); | |||||
userInfoDetails.setCompanyId(userFullInfoDTO.getCompanyId()); | |||||
userInfoDetails.setIdentifier(userFullInfoDTO.getIdentifier()); | |||||
userInfoDetails.setPassword(userFullInfoDTO.getCredential()); | |||||
return userInfoDetails; | |||||
} | |||||
} |
@@ -1,6 +1,7 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
package com.ningdatech.pmapi.user.security.auth.credential; | |||||
import com.ningdatech.basic.exception.BizException; | import com.ningdatech.basic.exception.BizException; | ||||
import com.ningdatech.pmapi.user.constant.LoginTypeEnum; | |||||
import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
import org.springframework.http.HttpMethod; | import org.springframework.http.HttpMethod; | ||||
import org.springframework.security.authentication.AuthenticationServiceException; | import org.springframework.security.authentication.AuthenticationServiceException; | ||||
@@ -24,8 +25,9 @@ public class UsernamePasswordAuthFilter extends AbstractAuthenticationProcessing | |||||
private boolean postOnly = true; | private boolean postOnly = true; | ||||
private static final String USERNAME_PARAMETER = "username"; | |||||
private static final String PASSWORD_PARAMETER = "password"; | |||||
private static final String IDENTIFIER_PARAMETER = "identifier"; | |||||
private static final String CREDENTIAL_PARAMETER = "credential"; | |||||
private static final String LOGIN_TYPE_PARAMETER = "loginType"; | |||||
// ~ Constructors | // ~ Constructors | ||||
@@ -44,15 +46,22 @@ public class UsernamePasswordAuthFilter extends AbstractAuthenticationProcessing | |||||
if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { | if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { | ||||
throw new AuthenticationServiceException("请求方法错误"); | throw new AuthenticationServiceException("请求方法错误"); | ||||
} | } | ||||
String username = request.getParameter(USERNAME_PARAMETER); | |||||
String password = request.getParameter(PASSWORD_PARAMETER); | |||||
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { | |||||
String identifier = request.getParameter(IDENTIFIER_PARAMETER); | |||||
String credential = request.getParameter(CREDENTIAL_PARAMETER); | |||||
String loginType = request.getParameter(LOGIN_TYPE_PARAMETER); | |||||
if (StringUtils.isBlank(loginType)) { | |||||
throw new BadCredentialsException("登陆类型不能为空"); | |||||
} | |||||
if (StringUtils.isBlank(identifier) || StringUtils.isBlank(credential)) { | |||||
throw new UsernameNotFoundException("用户名或密码不能为空"); | throw new UsernameNotFoundException("用户名或密码不能为空"); | ||||
} | } | ||||
username = username.trim(); | |||||
password = password.trim(); | |||||
identifier = identifier.trim(); | |||||
credential = credential.trim(); | |||||
loginType = loginType.trim(); | |||||
try { | try { | ||||
UsernamePasswordAuthToken authRequest = new UsernamePasswordAuthToken(username, password); | |||||
CredentialAuthToken authRequest = new CredentialAuthToken(identifier, credential, loginType); | |||||
// Allow subclasses to set the "details" property | // Allow subclasses to set the "details" property | ||||
setDetails(request, authRequest); | setDetails(request, authRequest); | ||||
return this.getAuthenticationManager().authenticate(authRequest); | return this.getAuthenticationManager().authenticate(authRequest); | ||||
@@ -65,7 +74,31 @@ public class UsernamePasswordAuthFilter extends AbstractAuthenticationProcessing | |||||
} | } | ||||
} | } | ||||
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthToken authRequest) { | |||||
protected void setDetails(HttpServletRequest request, CredentialAuthToken authRequest) { | |||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); | authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); | ||||
} | } | ||||
private void valid(String identifier, String credential, String loginType) { | |||||
LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(loginType); | |||||
switch (loginTypeEnum) { | |||||
case DING_QR_LOGIN: { | |||||
if (StringUtils.isBlank(credential)) { | |||||
throw new BadCredentialsException("浙政钉扫码登陆 授权码 不能为空 credential"); | |||||
} | |||||
} | |||||
break; | |||||
case USERNAME_PASSWORD_LOGIN: { | |||||
if (StringUtils.isBlank(identifier) || StringUtils.isBlank(credential)) { | |||||
throw new BadCredentialsException("账号密码登陆 账号密码不能为空 identifier credential"); | |||||
} | |||||
} | |||||
break; | |||||
case PHONE_VERIFICATION_CODE_LOGIN: { | |||||
if (StringUtils.isBlank(identifier) || StringUtils.isBlank(credential)) { | |||||
throw new BadCredentialsException("手机号验证码登陆 手机号或验证码不能为空 identifier credential"); | |||||
} | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
} | } |
@@ -1,5 +1,7 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
package com.ningdatech.pmapi.user.security.auth.credential; | |||||
import com.ningdatech.pmapi.user.constant.LoginTypeEnum; | |||||
import com.ningdatech.zwdd.client.ZwddAuthClient; | |||||
import org.springframework.security.authentication.AuthenticationProvider; | import org.springframework.security.authentication.AuthenticationProvider; | ||||
import org.springframework.security.authentication.BadCredentialsException; | import org.springframework.security.authentication.BadCredentialsException; | ||||
import org.springframework.security.authentication.InternalAuthenticationServiceException; | import org.springframework.security.authentication.InternalAuthenticationServiceException; | ||||
@@ -20,25 +22,46 @@ public class UsernamePasswordAuthProvider implements AuthenticationProvider { | |||||
private PasswordEncoder passwordEncoder; | private PasswordEncoder passwordEncoder; | ||||
private ZwddAuthClient zwddAuthClient; | |||||
@Override | @Override | ||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException { | public Authentication authenticate(Authentication authentication) throws AuthenticationException { | ||||
if (!(authentication instanceof UsernamePasswordAuthToken)) { | |||||
if (!(authentication instanceof CredentialAuthToken)) { | |||||
throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken"); | throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken"); | ||||
} | } | ||||
UsernamePasswordAuthToken authenticationToken = (UsernamePasswordAuthToken) authentication; | |||||
CredentialAuthToken authenticationToken = (CredentialAuthToken) authentication; | |||||
String credentials = (String) authenticationToken.getCredentials(); | |||||
UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); | |||||
if (user == null) { | |||||
throw new InternalAuthenticationServiceException("can not get user info!"); | |||||
UserDetails user = null; | |||||
LoginTypeEnum loginTypeEnum = authenticationToken.getLoginTypeEnum(); | |||||
switch (loginTypeEnum) { | |||||
case DING_QR_LOGIN: { | |||||
// TODO 补充浙政钉扫码逻辑 | |||||
user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); | |||||
} | |||||
break; | |||||
case PHONE_VERIFICATION_CODE_LOGIN: { | |||||
// TODO | |||||
user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); | |||||
} | |||||
break; | |||||
case USERNAME_PASSWORD_LOGIN: { | |||||
user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); | |||||
if (user == null) { | |||||
throw new InternalAuthenticationServiceException("can not get user info!"); | |||||
} | |||||
// 账号密码登陆 更改 | |||||
additionalAuthenticationChecks(user, authenticationToken); | |||||
} | |||||
break; | |||||
} | } | ||||
// TODO 开发使用暂时关闭账号密码验证 | |||||
// additionalAuthenticationChecks(user, authenticationToken); | |||||
// 校验用户是否有当前端的登陆权限 | |||||
// 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 | // 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 | ||||
return new UsernamePasswordAuthToken(user, user.getPassword(), user.getAuthorities()); | |||||
return new CredentialAuthToken(user, user.getPassword(), user.getAuthorities()); | |||||
} | } | ||||
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthToken authentication) | |||||
protected void additionalAuthenticationChecks(UserDetails userDetails, CredentialAuthToken authentication) | |||||
throws AuthenticationException { | throws AuthenticationException { | ||||
if (authentication.getCredentials() == null) { | if (authentication.getCredentials() == null) { | ||||
throw new BadCredentialsException("login fail! password is null"); | throw new BadCredentialsException("login fail! password is null"); | ||||
@@ -51,7 +74,7 @@ public class UsernamePasswordAuthProvider implements AuthenticationProvider { | |||||
@Override | @Override | ||||
public boolean supports(Class<?> authentication) { | public boolean supports(Class<?> authentication) { | ||||
return UsernamePasswordAuthToken.class.isAssignableFrom(authentication); | |||||
return CredentialAuthToken.class.isAssignableFrom(authentication); | |||||
} | } | ||||
public void setUserDetailsService(UserDetailsService userDetailsService) { | public void setUserDetailsService(UserDetailsService userDetailsService) { | ||||
@@ -62,4 +85,8 @@ public class UsernamePasswordAuthProvider implements AuthenticationProvider { | |||||
this.passwordEncoder = passwordEncoder; | this.passwordEncoder = passwordEncoder; | ||||
} | } | ||||
public void setZwddAuthClient(ZwddAuthClient zwddAuthClient) { | |||||
this.zwddAuthClient = zwddAuthClient; | |||||
} | |||||
} | } |
@@ -2,19 +2,11 @@ | |||||
integration: | integration: | ||||
zzd: | zzd: | ||||
#扫码 | #扫码 | ||||
app-auth-key: expert-base_dingoa-c5nnefYVnie | |||||
app-auth-secret: nm8qtST8uK431HYrjr7srcE23sT4889QgMcYFM3L | |||||
# #免登/获取信息 | |||||
# app-key: file-manage-4Mjx9358wuxjyYFjY3 | |||||
# app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O | |||||
app-auth-key: ls-rebuild_dingoa-rgeWs3YVr26z | |||||
app-auth-secret: 37qCe6ylNMW0N8K2741z0c2b9vJP2gtuMRQQtZ9P | |||||
#免登/获取信息 | |||||
app-key: ls_rebuild-10c8n5X0707yFV7jURr | app-key: ls_rebuild-10c8n5X0707yFV7jURr | ||||
app-secret: gN8J3WazyXLMWKDuFmx6C4yaH5lFUY41x8rYLLo6 | app-secret: gN8J3WazyXLMWKDuFmx6C4yaH5lFUY41x8rYLLo6 | ||||
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729 | #专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729 | ||||
tenantId: 31141 | tenantId: 31141 | ||||
domain: openplatform.dg-work.cn | |||||
# integration.zzd.enabled=true | |||||
# #扫码 | |||||
# integration.zzd.app-auth-key=file-manage_dingoa-zte2LbiAfIj | |||||
# integration.zzd.app-auth-secret=H794aFZf271QbfUr50pbBpBTlXSrWIP71q9RTR34 | |||||
# integration.zzd.domain=openplatform.dg-work.cn | |||||
domain: openplatform.dg-work.cn |