From 3520e86e2b00b9c1ee3f4fffd4ab49fe3d6c259e Mon Sep 17 00:00:00 2001 From: 黎星凯 <13949086503@163.com> Date: 星期五, 17 五月 2024 15:29:21 +0800 Subject: [PATCH] 20240517修改: 关联源模块 --- iplatform-base-security-consum/src/test/java/com/iplatform/security/TestSecurity.java | 37 iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetails.java | 171 +++ iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFailureHandler.java | 59 + iplatform-base-security-consum/src/main/java/com/iplatform/security/JwtAuthenticationTokenFilter.java | 195 +++ iplatform-base-security-consum/src/main/java/com/iplatform/security/util/MockPrincipalUtils.java | 53 iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationSuccessHandler.java | 38 iplatform-base-security-consum/src/main/java/com/iplatform/security/FailedAuthenticationEntryPoint.java | 36 iplatform-base-security-consum/src/main/java/com/iplatform/security/controller/SecurityController.java | 439 +++++++ iplatform-base-security-consum/src/main/java/com/iplatform/security/exception/PcUserStopAppException.java | 20 pom.xml | 7 deploy-jar-single/src/main/resources/application.yml | 2 iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationProvider.java | 99 + iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultSecuritySpi.java | 397 +++++++ iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/NoneCaptchaLoginCallback.java | 11 iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetailsService.java | 209 +++ iplatform-base-security-consum/src/main/java/com/iplatform/security/util/ResourceLoaderUtils.java | 5 iplatform-base-security-consum/src/main/java/com/iplatform/security/util/LoginCallbackUtils.java | 69 + iplatform-base-security-consum/src/main/java/com/iplatform/security/config/WebSecurityConfig.java | 492 ++++++++ iplatform-base-security-consum/src/main/java/com/iplatform/security/util/SecurityConfigUtils.java | 58 + iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultLogoutSuccessHandler.java | 81 + admin-web/public/static/config.js | 8 iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SmsCodeLoginCallback.java | 76 + iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultResourceLoaderProvider.java | 257 ++++ consum-base/pom.xml | 2 iplatform-base-security-consum/pom.xml | 49 iplatform-base-security-consum/src/main/java/com/iplatform/security/event/RoleSecurityUpdateListener.java | 40 iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/ThirdPartyLoginCallback.java | 33 iplatform-base-security-consum/src/main/java/com/iplatform/security/config/SecurityProperties.java | 172 +++ iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SimplePasswordLoginCallback.java | 39 iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/MobilePassCaptchaLoginCallback.java | 31 iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/EncryptPasswordLoginCallback.java | 57 + iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFilter.java | 35 iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/WechatLoginCallback.java | 34 iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationToken.java | 31 34 files changed, 3,336 insertions(+), 6 deletions(-) diff --git a/admin-web/public/static/config.js b/admin-web/public/static/config.js index 77b3c75..3e156e6 100644 --- a/admin-web/public/static/config.js +++ b/admin-web/public/static/config.js @@ -9,8 +9,8 @@ // 鎺ュ彛璇锋眰鍦板潃 - ftpUrl: 'http://172.16.20.9:8083/lowConsum',//寮�鍙� - apiBaseURL: 'http://172.16.20.9:8083/lowConsum',//寮�鍙� + // ftpUrl: 'http://172.16.20.9:8083/lowConsum',//寮�鍙� + // apiBaseURL: 'http://172.16.20.9:8083/lowConsum',//寮�鍙� // apiBaseURL: 'http://172.16.60.110:8083/lowConsum',//寮�鍙� @@ -20,8 +20,8 @@ // apiBaseURL: protocol + '//'+ host + '/lowapi',// 姝e紡, - // ftpUrl: protocol + '//'+ host + '/lowapi',// 姝e紡, - // apiBaseURL: protocol + '//'+ host + '/lowapi',// 姝e紡, + ftpUrl: protocol + '//'+ host + '/lowapi',// 姝e紡, + apiBaseURL: protocol + '//'+ host + '/lowapi',// 姝e紡, debug: false //璋冭瘯寮�鍏� true鏃朵細杈撳嚭璇锋眰鏃ュ織 }; diff --git a/consum-base/pom.xml b/consum-base/pom.xml index 0edc9dd..8c0f307 100644 --- a/consum-base/pom.xml +++ b/consum-base/pom.xml @@ -39,7 +39,7 @@ <!-- 寮曞叆web瀹夊叏璁よ瘉妯″潡锛屽鏋滀笉寮曞叆鍒欎笉浼氬仛浠讳綍鏉冮檺鎷︽埅锛堣繖绉嶆ā寮忛�氬父鍙敤浜庡揩閫熸祴璇曪級, 2022/10/31 --> <dependency> <groupId>com.iplatform</groupId> - <artifactId>iplatform-base-security</artifactId> + <artifactId>iplatform-base-security-consum</artifactId> <exclusions> <exclusion> <artifactId>spring-security-crypto</artifactId> diff --git a/deploy-jar-single/src/main/resources/application.yml b/deploy-jar-single/src/main/resources/application.yml index a17ec4c..fadf7d2 100644 --- a/deploy-jar-single/src/main/resources/application.yml +++ b/deploy-jar-single/src/main/resources/application.yml @@ -1,4 +1,4 @@ spring: profiles: - active: test + active: prod diff --git a/iplatform-base-security-consum/pom.xml b/iplatform-base-security-consum/pom.xml new file mode 100644 index 0000000..219ab9a --- /dev/null +++ b/iplatform-base-security-consum/pom.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>iplatform</artifactId> + <groupId>com.iplatform</groupId> + <version>2.3.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>iplatform-base-security-consum</artifactId> + <packaging>jar</packaging> + <version>1.0.0-SNAPSHOT</version> + + <properties> + </properties> + + <!-- + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ WEB瀹夊叏妯″潡渚濊禆 iplatform-base锛屼綔涓轰竴涓彲閫夋敮鎸佹ā鍧椼�� + ~ 涓氬姟搴旂敤濡傛灉闇�瑕佸紩鍏ヨ妯″潡鍗冲彲锛屽鏋滀娇鐢� gateway 妯″紡鍒欐棤闇�浣跨敤璇ユā鍧椼�� + ~ 2022-10-26 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + --> + <dependencies> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <!-- 閫氳繃鍩虹搴撳紩鍏�: spring-security, 2022/10/31 --> + <dependency> + <groupId>com.walkersoft</groupId> + <artifactId>walker-web-security</artifactId> + </dependency> + + <!-- 骞冲彴鍩虹妯″潡蹇呴』瀛樺湪, 2022/10/31 --> + <dependency> + <groupId>com.iplatform</groupId> + <artifactId>iplatform-base</artifactId> + <scope>provided</scope> + </dependency> + + </dependencies> + +</project> diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFailureHandler.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFailureHandler.java new file mode 100644 index 0000000..8f0ba15 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFailureHandler.java @@ -0,0 +1,59 @@ +package com.iplatform.security; + +import com.iplatform.security.exception.PcUserStopAppException; +import com.walker.infrastructure.utils.JsonUtils; +import com.walker.web.ResponseCode; +import com.walker.web.ResponseValue; +import com.walker.web.util.ServletUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.CredentialsExpiredException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.authentication.LockedException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandler { + + protected final transient Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public void onAuthenticationFailure(HttpServletRequest request + , HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + String message = null; //鎻愮ず淇℃伅 + int code = ResponseCode.USER_CREDENTIALS_ERROR.getCode(); //閿欒缂栫爜 + + if(exception instanceof AccountExpiredException){ + message = ResponseCode.USER_ACCOUNT_EXPIRED.getMessage(); + logger.debug("---------> " + message); + }else if(exception instanceof BadCredentialsException){ + message = ResponseCode.USER_CREDENTIALS_ERROR.getMessage(); + }else if(exception instanceof CredentialsExpiredException){ + message = "瀵嗙爜杩囨湡,鐧诲綍澶辫触锛�"; + }else if(exception instanceof DisabledException){ + message = ResponseCode.USER_ACCOUNT_DISABLE.getMessage(); + }else if(exception instanceof LockedException){ + message = ResponseCode.USER_ACCOUNT_LOCKED.getMessage(); + }else if(exception instanceof InternalAuthenticationServiceException){ + message = ResponseCode.USER_CREDENTIALS_ERROR.getMessage(); + }else if(exception instanceof PcUserStopAppException){ + message = PcUserStopAppException.MESSAGE; + }else{ + message = "鐧诲綍澶辫触锛�"; + } + + try { + ServletUtils.renderString(response, JsonUtils.objectToJsonString(ResponseValue.error(message))); + } catch (Exception e) { + logger.error("璁よ瘉澶辫触:" + request.getRequestURI(), e); + } + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFilter.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFilter.java new file mode 100644 index 0000000..7748085 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationFilter.java @@ -0,0 +1,35 @@ +package com.iplatform.security; + +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * DefaultAuthenticationToken 閲嶅啓鍚庯紝鐧诲綍鎬绘槸鎶ラ敊: 鐢ㄦ埛鍚嶆垨瀵嗙爜閿欒锛屽皾璇曢噸鍐欒杩囨护鍣ㄣ�� + * @author 鏃跺厠鑻� + * @date 2023-01-27 + */ +@Deprecated +public class DefaultAuthenticationFilter extends UsernamePasswordAuthenticationFilter { + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { +// if (this.postOnly && !request.getMethod().equals("POST")) { + if (!request.getMethod().equals("POST")) { + throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); + } else { + String username = this.obtainUsername(request); + username = username != null ? username.trim() : ""; + String password = this.obtainPassword(request); + password = password != null ? password : ""; +// UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password); + DefaultAuthenticationToken authRequest = (DefaultAuthenticationToken)DefaultAuthenticationToken.unauthenticated(username, password); + this.setDetails(request, authRequest); + return this.getAuthenticationManager().authenticate(authRequest); + } + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationProvider.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationProvider.java new file mode 100644 index 0000000..9231170 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationProvider.java @@ -0,0 +1,99 @@ +package com.iplatform.security; + +import com.iplatform.base.PlatformLoginCallback; +import com.iplatform.base.pojo.RequestLogin; +import com.iplatform.security.exception.PcUserStopAppException; +import com.iplatform.security.util.LoginCallbackUtils; +import com.walker.web.CaptchaType; +import com.walker.web.ClientType; +import com.walker.web.LoginType; +import com.walker.web.ResponseCode; +import com.walker.web.UserType; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +/** + * 鑷畾涔夎璇佹彁渚涜�咃紝鐢卞钩鍙拌嚜宸卞喅瀹氬浣曞姣斿瘑鐮侀獙璇侊紝濡傛灉涓嶅畾鍒跺垯spring浼氳嚜鍔ㄦ瘮杈冨瘑鐮併�� + * @author 鏃跺厠鑻� + * @date 2023-01-28 + */ +public class DefaultAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { + + @Override + protected void additionalAuthenticationChecks(UserDetails userDetails + , UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + if(!(authentication instanceof DefaultAuthenticationToken)){ + throw new InternalAuthenticationServiceException("UsernamePasswordAuthenticationToken 蹇呴』鏄�: DefaultAuthenticationToken", null); + } + DefaultAuthenticationToken defaultAuthenticationToken = (DefaultAuthenticationToken)authentication; + RequestLogin requestLogin = defaultAuthenticationToken.getRequestLogin(); + + // 闈濧PP鐢ㄦ埛鑳藉惁鐧诲綍鎵嬫満APP锛熷彲浠ュ湪杩欓噷鍒ゆ柇锛�2023-03-20 + if(!this.allowPcUserAccessApp){ + if(requestLogin.getClientType().equalsIgnoreCase(ClientType.MOBILE.getIndex())){ + DefaultUserDetails defaultUserDetails = (DefaultUserDetails) userDetails; + if(defaultUserDetails.getUserPrincipal().getUserInfo().getUser_type() != UserType.TYPE_APP_REG){ + // 鐧诲綍鏂瑰紡涓虹Щ鍔ㄧ锛屽悓鏃剁敤鎴风被鍒负闈瀉pp鐢ㄦ埛锛岀姝㈢櫥褰� + throw new PcUserStopAppException(null); + } + } + } + + // 閫氳繃鐧诲綍绫诲瀷锛岃幏鍙栭厤缃殑鐧诲綍鍥炶皟瀵硅薄锛屽娲惧疄鐜板瘑鐮侀獙璇併�� + // 2023-12-28 绉诲姩绔櫥褰曢獙璇� + CaptchaType captchaType = CaptchaType.getType(requestLogin.getVerifyType()); + PlatformLoginCallback loginCallback = LoginCallbackUtils.getLoginCallbackBean(LoginType.getType(requestLogin.getLoginType()), true, captchaType); + if(loginCallback == null){ + throw new InternalAuthenticationServiceException("loginCallback鏈壘鍒�:" + requestLogin.getLoginType()); + } + boolean success = loginCallback.validatePassword(((DefaultUserDetails)userDetails).getUserPrincipal()); + if(!success){ + throw new BadCredentialsException(ResponseCode.USER_CREDENTIALS_ERROR.getMessage()); + } + logger.debug("++++++++++++ 鑷姩楠岃瘉瀵嗙爜涓烘纭�, loginType = " + requestLogin.getLoginType()); + } + + @Override + protected UserDetails retrieveUser(String username + , UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + try{ + UserDetails loadedUser = this.userDetailsService.loadUserByUsername(username); + if(loadedUser == null){ + throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation"); + } + return loadedUser; + + } catch (Exception ex){ + if(ex instanceof UsernameNotFoundException){ + logger.debug("+++++++++++++++ " + ex.getMessage()); + throw ex; + } + if(ex instanceof InternalAuthenticationServiceException){ + throw ex; + } + throw new InternalAuthenticationServiceException(ex.getMessage(), ex); + } + } + + public void setUserDetailsService(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + + /** + * 璁剧疆鏄惁鍏佽'鍚庡彴PC鐢ㄦ埛'璁块棶鐧诲綍鎵嬫満APP + * @param allowPcUserAccessApp + * @date 2023-03-20 + */ + public void setAllowPcUserAccessApp(boolean allowPcUserAccessApp) { + this.allowPcUserAccessApp = allowPcUserAccessApp; + } + + private boolean allowPcUserAccessApp = true; + private UserDetailsService userDetailsService; +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationSuccessHandler.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationSuccessHandler.java new file mode 100644 index 0000000..6ddd13d --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationSuccessHandler.java @@ -0,0 +1,38 @@ +package com.iplatform.security; + +import com.walker.web.TokenGenerator; +import com.walker.web.UserPrincipal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Deprecated +public class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + protected final transient Logger logger = LoggerFactory.getLogger(getClass()); + + private TokenGenerator tokenGenerator; + + public void setTokenGenerator(TokenGenerator tokenGenerator) { + this.tokenGenerator = tokenGenerator; + } + + @Override + public void onAuthenticationSuccess(HttpServletRequest request + , HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + + // 1.鑾峰彇閫氳繃璁よ瘉鐢ㄦ埛瀵硅薄 + // 2.鐢熸垚Token淇℃伅 + // 3.鍏宠仈Token涓庣敤鎴蜂俊鎭紝骞跺瓨鍌ㄥ埌缂撳瓨(鍐呭瓨)涓� + // 4.杩斿洖瀹㈡埛绔�:鐢ㄦ埛浠ュ強Token + logger.info("onAuthenticationSuccess = " + authentication.getPrincipal()); + UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); + + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationToken.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationToken.java new file mode 100644 index 0000000..1301381 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultAuthenticationToken.java @@ -0,0 +1,31 @@ +package com.iplatform.security; + +import com.iplatform.base.pojo.RequestLogin; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; + +/** + * 閲嶅啓榛樿鐨勮璇乼oken瀵硅薄锛屾坊鍔犺嚜瀹氫箟灞炴�с�� + * @author 鏃跺厠鑻� + * @date 2023-01-27 + */ +public class DefaultAuthenticationToken extends UsernamePasswordAuthenticationToken { + + private RequestLogin requestLogin; + + /** + * 杩斿洖璇锋眰鐧诲綍鎻愪氦鐨勫師濮嬫暟鎹� + * @return + */ + public RequestLogin getRequestLogin() { + return requestLogin; + } + + public DefaultAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + } + + public DefaultAuthenticationToken(Object principal, Object credentials, RequestLogin requestLogin){ + super(principal, credentials); + this.requestLogin = requestLogin; + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultLogoutSuccessHandler.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultLogoutSuccessHandler.java new file mode 100644 index 0000000..fd565cd --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultLogoutSuccessHandler.java @@ -0,0 +1,81 @@ +package com.iplatform.security; + +import com.iplatform.base.UserLoginCache; +import com.iplatform.base.VariableConstants; +import com.iplatform.base.callback.AfterLoginCallback; +import com.iplatform.base.callback.PlatformCallbackPostProcessor; +import com.iplatform.base.util.TokenUtils; +import com.walker.infrastructure.utils.StringUtils; +import com.walker.web.ResponseValue; +import com.walker.web.TokenException; +import com.walker.web.TokenGenerator; +import com.walker.web.UserOnlineProvider; +import com.walker.web.util.ServletUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class DefaultLogoutSuccessHandler implements LogoutSuccessHandler { + + protected final transient Logger logger = LoggerFactory.getLogger(getClass()); + + private UserOnlineProvider userOnlineProvider; + + private TokenGenerator tokenGenerator; + + private UserLoginCache userLoginCache; + + public void setUserLoginCache(UserLoginCache userLoginCache) { + this.userLoginCache = userLoginCache; + } + + public void setTokenGenerator(TokenGenerator tokenGenerator) { + this.tokenGenerator = tokenGenerator; + } + + public void setUserOnlineProvider(UserOnlineProvider userOnlineProvider) { + this.userOnlineProvider = userOnlineProvider; + } + + @Override + public void onLogoutSuccess(HttpServletRequest request + , HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + String token = TokenUtils.getAuthorizationToken(request); + if(StringUtils.isNotEmpty(token)){ + try{ + String data = tokenGenerator.validateToken(token, VariableConstants.TOKEN_SECRET); + String[] userIdAndKey = TokenUtils.getUserIdAndKey(data); + this.userOnlineProvider.removeUserPrincipal(userIdAndKey[2]); + // 2023-07-11 鐢ㄦ埛鐧诲綍绛栫暐缂撳瓨涔熷垹闄� + this.userLoginCache.removeUserLogin(userIdAndKey[1]); + + // 2023-08-18锛岀櫥褰曟垚鍔熷洖璋� + AfterLoginCallback afterLoginCallback = PlatformCallbackPostProcessor.getCallbackObject(AfterLoginCallback.class); + if(afterLoginCallback != null){ + afterLoginCallback.onLogout(userIdAndKey[1]); + } + + logger.debug("鐢ㄦ埛 logout success: " + userIdAndKey[1]); + } catch (TokenException ex){ + logger.error("logout娉ㄩ攢鏃讹紝token瑙f瀽閿欒:" + ex.getMessage() + ", token=" + token, ex); + if(ex.isExpired()){ + this.recordLogoutInfo("null", "logout", "token瓒呮椂锛岄��鍑烘搷浣滄棤娉曞垹闄ょ紦瀛�"); + } else { + this.recordLogoutInfo("null", "logout", "token瓒呮椂锛岄��鍑烘搷浣滃紓甯�:" + ex.getMessage()); + } + } + } + ServletUtils.renderString(response, ResponseValue.success("閫�鍑烘垚鍔�")); + } + + private void recordLogoutInfo(String loginId, String status, String message){ + logger.debug("寮傛璁板綍閫�鍑烘棩蹇楋紝鍚庣画瑕佽ˉ鍏�:" + status + ", " + message); + } + +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultResourceLoaderProvider.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultResourceLoaderProvider.java new file mode 100644 index 0000000..f7bd564 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultResourceLoaderProvider.java @@ -0,0 +1,257 @@ +package com.iplatform.security; + +import com.iplatform.base.SecurityConstants; +import com.iplatform.base.cache.MenuCacheProvider; +import com.walker.infrastructure.utils.StringUtils; +import com.walker.web.Constants; +import com.walker.web.security.ResourceLoadProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.SecurityConfig; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 榛樿璧勬簮鍔犺浇鎻愪緵鑰咃紝security妗嗘灦闇�瑕佺殑鏉冮檺鐐归泦鍚堛�� + * @author 鏃跺厠鑻� + * @date 2022-11-02 + */ +public class DefaultResourceLoaderProvider implements ResourceLoadProvider { + + protected final transient Logger logger = LoggerFactory.getLogger(getClass()); + + private MenuCacheProvider menuCacheProvider = null; + + private Map<String, Collection<ConfigAttribute>> resultMap = new HashMap<String, Collection<ConfigAttribute>>(); + + /** 璇锋眰鍖归厤瀵硅薄鏀惧叆Map涓紝閬垮厤閲嶅鍒涘缓銆俴ey = url锛寁alue = AntPathRequestMatcher */ + private Map<String, AntPathRequestMatcher> requestMatchers = new ConcurrentHashMap<String, AntPathRequestMatcher>(); + + private Collection<ConfigAttribute> emptyAttributes = null; + private Collection<ConfigAttribute> anonymousAttributes = null; + // 2023-03-21 activiti7宸ヤ綔娴佸繀椤绘嫤鎴潈闄愶紝鍙樻�併�� + private Collection<ConfigAttribute> activiti7Attributes = null; + + private List<String> permitAccessUrls = null; + + private Map<String, String> anonymousUrlMap = null; + + /** + * 璁剧疆鍙尶鍚嶈闂殑鍏紑鍦板潃闆嗗悎锛屽: ["/login","/register", "/image/**"] + * @param anonymousUrlList + */ + public void setAnonymousUrlList(List<String> anonymousUrlList) { + if(!StringUtils.isEmptyList(anonymousUrlList)){ + this.anonymousUrlMap = new HashMap<>(); + for(String url : anonymousUrlList){ + this.anonymousUrlMap.put(url, StringUtils.EMPTY_STRING); + } + } + } + + /** + * 璁剧疆涓�浜涘彧瑕佽璇佺敤鎴烽兘鍙互璁块棶鐨勫父鐢╱rl锛屽: /api/**, /report/** 绛� + * @param permitAccessUrls + */ + public void setPermitAccessUrls(List<String> permitAccessUrls) { + this.permitAccessUrls = permitAccessUrls; + } + + public void setMenuCacheProvider(MenuCacheProvider menuCacheProvider) { + this.menuCacheProvider = menuCacheProvider; + } + + @Override + public Map<String, Collection<ConfigAttribute>> loadResource() { + resultMap.clear(); + requestMatchers.clear(); + + // 1-鎶婅彍鍗曞拰鍔熻兘鐐箄rl瑙掕壊鍏崇郴鏁寸悊鍒板璞′腑锛歶rlRoleMap + Map<String, List<String>> urlRoleMap = new HashMap<String, List<String>>(); + + // 2-鎵�鏈夎鑹插搴旂殑URL閮藉姞鍏� + List<String[]> roleUrlMap = this.menuCacheProvider.getAllRoleMenuMap(); + if(roleUrlMap != null && roleUrlMap.size() > 0){ + String url = null; + for(String[] entry : roleUrlMap){ + url = entry[1]; + if(StringUtils.isEmpty(url)){ + throw new NullPointerException("url is not null! role = " + entry[0]); + } + setUrlRoleMap(urlRoleMap, url, entry[0]); + } + } + + // 3-瓒呯骇绠$悊鍛橀粯璁ゅ姞涓婃墍鏈夎彍鍗曟潈闄� + List<String> allMenuUrl = this.menuCacheProvider.getAllMenuUrlList(); + if(!StringUtils.isEmptyList(allMenuUrl)){ + for(String url : allMenuUrl){ + setUrlRoleMap(urlRoleMap, url, SecurityConstants.ROLE_SUPER_ADMIN); + } + } + setUrlRoleMap(urlRoleMap, "/supervisor/**", SecurityConstants.ROLE_SUPER_ADMIN); +// setUrlRoleMap(urlRoleMap, "/wf/**", SecurityConstants.ROLE_SUPER_ADMIN); + + // 4-鎵�鏈夊凡鐧诲綍鐢ㄦ埛锛岄兘鍙互璁块棶榛樿鍏紑鍦板潃: /permit + setUrlRoleMap(urlRoleMap, "/permit/**", SecurityConstants.ROLE_USER); + + // 5-鍏朵粬涓�浜涘彲鐢ㄥ湴鍧�锛屽凡璁よ瘉鐢ㄦ埛閮藉彲浠ヨ闂紝鏃犻渶鍗曠嫭閰嶇疆鏉冮檺 + if(!StringUtils.isEmptyList(this.permitAccessUrls)){ + for(String url : this.permitAccessUrls){ + setUrlRoleMap(urlRoleMap, url, SecurityConstants.ROLE_USER); +// logger.debug("鍏叡璁块棶璧勬簮锛�" + url); +// logger.debug(urlRoleMap.toString()); + } + } + + // 6-鍖垮悕URL涓嶆嫤鎴� + if(this.anonymousUrlMap != null){ + for(String url : this.anonymousUrlMap.keySet()){ + setUrlRoleMap(urlRoleMap, url, Constants.ROLE_ANONYMOUS); + } + } + + // 7-activiti7宸ヤ綔娴佹潈闄愶紝蹇呴』鍔犱笂銆�2023-03-21 + this.setUrlRoleMap(urlRoleMap, "/wf/**", Constants.ROLE_ACTIVITI_USER); + + logger.info("鍏卞姞杞芥潈闄愮偣: " + urlRoleMap.size()); +// if(logger.isDebugEnabled()){ +// for(Map.Entry<String, List<String>> entry : urlRoleMap.entrySet()){ +// logger.debug(entry.getKey() + " = " + entry.getValue()); +// } +// } + + // 6-杞垚spring security 鐗瑰畾鏉冮檺灞炴�� + if(urlRoleMap.size() > 0){ + List<ConfigAttribute> caList = null; + for(Map.Entry<String, List<String>> entry : urlRoleMap.entrySet()){ + caList = new ArrayList<ConfigAttribute>(entry.getValue().size()+1); + for(String s : entry.getValue()){ + ConfigAttribute ca = new SecurityConfig(s); + caList.add(ca); + } + resultMap.put(entry.getKey(), caList); + } + } + + // 7-鍒濆鍖栬姹傝矾寰勫尮閰嶆牎楠屽璞� + Iterator<String> it = resultMap.keySet().iterator(); + String resURL = null; + AntPathRequestMatcher requestMatcher = null; + while(it.hasNext()){ + resURL = it.next(); + requestMatcher = requestMatchers.get(resURL); + // 鎶妑equestMatcher瀵硅薄鏀惧埌Map涓紝閬垮厤閲嶅鍒涘缓 + if(requestMatcher == null){ + requestMatcher = new AntPathRequestMatcher(resURL); + requestMatchers.put(resURL, requestMatcher); + } + } + return resultMap; + } + + @Override + public void reloadResource() { + this.loadResource(); + logger.info("ResourceLoaderProvider reload success!"); + } + + @Override + public Collection<ConfigAttribute> getAttributes(Object object) { + if(resultMap == null) return getEmptyAttributes(); + + Iterator<String> it = resultMap.keySet().iterator(); + + String srcURL = null; + String resURL = null; + AntPathRequestMatcher requestMatcher = null; + + while(it.hasNext()){ + resURL = it.next(); + requestMatcher = requestMatchers.get(resURL); + // 鎶妑equestMatcher瀵硅薄鏀惧埌Map涓紝閬垮厤閲嶅鍒涘缓 + if(requestMatcher == null){ + requestMatcher = new AntPathRequestMatcher(resURL); + requestMatchers.put(resURL, requestMatcher); + } + srcURL = ((FilterInvocation)object).getRequestUrl(); + if(requestMatcher.matches(((FilterInvocation)object).getRequest())){ + logger.debug("............> 鎵惧埌浜嗗尮閰嶇殑璧勬簮: " + resURL + ", 璇锋眰鐨勮祫婧�: " + srcURL); + // 2023-03-21 activiti7淇敼锛屽綋璁块棶娴佺▼鐩稿叧鍔熻兘锛岀粰浜堟祦绋嬩笓鐢ㄨ鑹� + // 杩欐槸activiti7鏈哄埗闇�瑕佺殑锛屽彉鎬侊紒 + if(resURL.startsWith(SecurityConstants.URL_WORKFLOW_PREFIX)){ + logger.debug("杩斿洖activiti7鐨勮鑹查泦鍚�"); + return this.getActiviti7Attributes(); + } + return resultMap.get(resURL); + } + } + + // 2022-11-13 + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // 濡傛灉閫氳繃琛ㄨ揪寮忔病鏈夊尮閰嶅埌URL锛岃繖閲岃妫�鏌ユ槸鍚﹀尶鍚嶈矾寰� + // 娉ㄦ剰锛氫笉鑳芥妸鍒ゆ柇鏀惧湪鍓嶉潰锛屽洜涓虹敤鎴烽厤缃尶鍚嶅湴鍧�鍙兘甯︽湁閫氶厤绗︼紝濡傦細/nano/** + // 浣嗘槸杩欓噷request鑾峰緱鐨刄RI鏄壒瀹氬湴鍧�锛屽: /nano/123 + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if(this.anonymousUrlMap != null && this.anonymousUrlMap.get(srcURL) != null){ + return this.getAnonymousAttributes(); + } + + // 濡傛灉鏍规嵁URL娌℃湁鎵惧埌瀵瑰簲鐨勮鑹查泦鍚堬紝灏辫繑鍥炰竴涓┖闆嗗悎锛� + // 鍥犱负spring security榛樿瀵逛簬绌洪泦鍚堥兘鏀捐銆� + return getEmptyAttributes(); + } + + @Override + public Collection<ConfigAttribute> getAttributesByUri(String uri) { + return null; + } + + private void setUrlRoleMap(Map<String, List<String>> urlRoleMap, String _url, String _roleId){ + List<String> _roles = urlRoleMap.get(_url); + if(_roles == null){ + _roles = new ArrayList<String>(8); + _roles.add(_roleId); + urlRoleMap.put(_url, _roles); + } else if(!_roles.contains(_roleId)){ + _roles.add(_roleId); + } + } + + protected Collection<ConfigAttribute> getEmptyAttributes(){ + if(emptyAttributes == null){ + emptyAttributes = new ArrayList<ConfigAttribute>(2); + emptyAttributes.add(new SecurityConfig(Constants.ROLE_EMPTY)); + } + return emptyAttributes; + } + protected Collection<ConfigAttribute> getAnonymousAttributes(){ + if(anonymousAttributes == null){ + anonymousAttributes = new ArrayList<ConfigAttribute>(2); + anonymousAttributes.add(new SecurityConfig(Constants.ROLE_ANONYMOUS)); + } + return emptyAttributes; + } + + /** + * 杩斿洖Activiti7闇�瑕佺殑瑙掕壊闆嗗悎銆� + * @return + * @date 2023-03-21 + */ + protected Collection<ConfigAttribute> getActiviti7Attributes(){ + if(this.activiti7Attributes == null){ + activiti7Attributes = new ArrayList<ConfigAttribute>(2); + activiti7Attributes.add(new SecurityConfig(Constants.ROLE_ACTIVITI_USER)); + } + return this.activiti7Attributes; + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultSecuritySpi.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultSecuritySpi.java new file mode 100644 index 0000000..fa01fd1 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultSecuritySpi.java @@ -0,0 +1,397 @@ +package com.iplatform.security; + +import com.iplatform.base.ArgumentsConstants; +import com.iplatform.base.AsyncManager; +import com.iplatform.base.PlatformLoginCallback; +import com.iplatform.base.SecurityConstants; +import com.iplatform.base.SecuritySpi; +import com.iplatform.base.VariableConstants; +import com.iplatform.base.callback.AfterLoginCallback; +import com.iplatform.base.callback.PlatformCallbackPostProcessor; +import com.iplatform.base.config.LogProperties; +import com.iplatform.base.exception.LoginException; +import com.iplatform.base.pojo.RequestLogin; +import com.iplatform.base.service.LogServiceImpl; +import com.iplatform.base.service.LoginServiceImpl; +import com.iplatform.base.support.strategy.LoginStrategyManager; +import com.iplatform.base.util.TokenUtils; +import com.iplatform.base.util.UserUtils; +import com.iplatform.core.BeanContextAware; +import com.iplatform.model.po.S_login_info; +import com.iplatform.model.po.S_user_core; +import com.iplatform.model.po.S_user_login; +import com.iplatform.security.config.SecurityProperties; +import com.iplatform.security.util.LoginCallbackUtils; +import com.iplatform.security.util.SecurityConfigUtils; +import com.walker.cache.CacheProvider; +import com.walker.infrastructure.arguments.ArgumentsManager; +import com.walker.infrastructure.arguments.Variable; +import com.walker.infrastructure.utils.DateUtils; +import com.walker.infrastructure.utils.NumberGenerator; +import com.walker.infrastructure.utils.StringUtils; +import com.walker.web.CaptchaProvider; +import com.walker.web.CaptchaResult; +import com.walker.web.CaptchaType; +import com.walker.web.Constants; +import com.walker.web.LoginType; +import com.walker.web.ResponseCode; +import com.walker.web.TokenGenerator; +import com.walker.web.UserOnlineProvider; +import com.walker.web.UserPrincipal; +import com.walker.web.WebAgentService; +import com.walker.web.WebRuntimeException; +import com.walker.web.WebUserAgent; +import com.walker.web.util.IdUtils; +import com.walker.web.util.ServletUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimerTask; + +public class DefaultSecuritySpi implements SecuritySpi { + + protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); + + public DefaultSecuritySpi(){} + + @Override + public boolean isAllowMobileLoginRegister(){ + return this.getSecurityProperties().isAllowMobileLoginReg(); + } + + @Override + public Map<String, Object> login(RequestLogin requestLogin) throws LoginException { + String username = requestLogin.getUsername(); + // 2023-01-26 涓轰簡鏀寔澶氱鐧诲綍鏂瑰紡锛屼娇鐢ㄧ櫥褰曞洖璋冨鐞嗗叿浣撶櫥褰曠粏鑺傘�� + // 2023-12-28 绉诲姩绔櫥褰曢獙璇� + CaptchaType captchaType = CaptchaType.getType(requestLogin.getVerifyType()); + PlatformLoginCallback loginCallback = LoginCallbackUtils.getLoginCallbackBean(LoginType.getType(requestLogin.getLoginType()), true, captchaType); + + boolean captchaEnabled = this.getArgumentVariable(ArgumentsConstants.KEY_SECURITY_CAPTCHA_ENABLED).getBooleanValue(); + // 2023-01-26 杩欓噷APP绔槸涓嶉渶瑕侀獙璇佺爜鐨� + if(captchaEnabled){ + CaptchaProvider<CaptchaResult> captchaProvider = loginCallback.getCaptchaProvider(); + if(captchaProvider == null){ +// return ResponseValue.error("绯荤粺闇�瑕侀獙璇佺爜锛屼絾鐧诲綍鏈厤缃�:" + loginCallback.getClass().getName()); + throw new LoginException("绯荤粺闇�瑕侀獙璇佺爜锛屼絾鐧诲綍鏈厤缃�:" + loginCallback.getClass().getName()); + } + if(StringUtils.isEmpty(requestLogin.getVerifyType())){ +// return ResponseValue.error("璇锋眰閿欒锛氶獙璇佺爜绫诲瀷涓虹┖"); + throw new LoginException("璇锋眰閿欒锛氶獙璇佺爜绫诲瀷涓虹┖"); + } + + // 绗笁鏂瑰鎺ョ殑璁よ瘉鐧诲綍锛屼笉闇�瑕佹娴嬮獙璇佺爜绫诲瀷鏄惁涓庡悗鍙颁竴鑷淬��2023-07-03 + if(captchaProvider.getCaptchaType() != CaptchaType.ThirdParty + && !requestLogin.getVerifyType().equals(captchaProvider.getCaptchaType().getIndex())){ + throw new LoginException("鍓嶇閰嶇疆鐨勯獙璇佺爜绫诲瀷涓庡悗鍙颁笉涓�鑷�! verifyType = " + captchaProvider.getCaptchaType()); + } + if(loginCallback.isValidateCaptcha()){ + logger.debug("闇�瑕侀獙璇佺爜锛実etCaptchaType={}", loginCallback.getCaptchaProvider().getCaptchaType()); + String error = this.validateCaptcha(requestLogin.getCode(), requestLogin.getUuid(), captchaProvider); + if(error != null){ +// return ResponseValue.error(error); + throw new LoginException(error); + } + } + } + + // 2023-07-11 妫�鏌ョ櫥褰曠瓥鐣ユ槸鍚︽弧瓒� + if(this.getLogProperties().isLoginEnabled()){ + String error = this.getLoginStrategyManager().execute(requestLogin); + if(error != null){ + throw new LoginException(error); + } + } + + // 鐢ㄦ埛楠岃瘉 + Authentication authentication = null; + + try{ +// UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + DefaultAuthenticationToken authenticationToken = new DefaultAuthenticationToken(username, requestLogin.getPassword(), requestLogin); + // 杩欓噷鏀惧叆绾跨▼锛屽悗闈serDetailsService浼氫娇鐢� + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + authentication = this.getAuthenticationManager().authenticate(authenticationToken); + + } catch (Exception e){ + this.recordLoginInfo(requestLogin.getUsername(), String.valueOf(ResponseCode.ERROR.getCode()), "鐧诲綍鏈垚鍔熻璇�", 0, null, null); + if(e instanceof UsernameNotFoundException){ +// throw new LoginException("鐢ㄦ埛璐﹀彿涓嶅瓨鍦紝鎴栧凡鍋滅敤锛�" + requestLogin.getUsername(), e, true); + throw new LoginException("鐢ㄦ埛璐﹀彿涓嶅瓨鍦紝鎴栧凡鍋滅敤锛�" + requestLogin.getUsername(), null, true); + } + if (e instanceof BadCredentialsException){ +// return ResponseValue.error(ResponseCode.USER_CREDENTIALS_ERROR.getCode(), ResponseCode.USER_CREDENTIALS_ERROR.getMessage()); + logger.debug("++++++++++++++++++ 瀵嗙爜閿欒"); + throw new LoginException(ResponseCode.USER_CREDENTIALS_ERROR.getMessage()); + } else { + // 2023-03-20 + // 鐧诲綍楠岃瘉鎶涘嚭寮傚父锛屼細鍦ㄨ繖閲岀粺涓�澶勭悊锛屽锛歅cUserStopAppException銆� + // DefaultAuthenticationProvider +// return ResponseValue.error(ResponseCode.USER_CREDENTIALS_ERROR.getCode(), e.getMessage()); + throw new LoginException(e.getMessage()); + } + } + + DefaultUserDetails userDetails = (DefaultUserDetails)authentication.getPrincipal(); + if(this.logger.isDebugEnabled()){ + logger.debug(userDetails.getUserPrincipal().toString()); + } + + // 2023-03-20锛屽浜庣┖楠岃瘉鐮佺被鍨嬶紙鐧诲綍鏂瑰紡锛夛紝闇�瑕佸悗鍙拌嚜鍔ㄧ敓鎴恥uid锛屽洜涓哄墠绔病鏈夋満浼氳姹傞獙璇佺爜鑾峰緱uuid + // 2023-07-03, 娣诲姞绗笁鏂瑰鎺ョ殑楠岃瘉绫诲瀷锛屼篃闇�瑕佽嚜鍔ㄧ敓鎴怳UID锛屽洜涓哄墠绔洿鎺ヨ姹傚悗鍙帮紙鐩墠棰勭畻涓�浣撳寲浣跨敤锛� + CaptchaType currentCaptchaType = loginCallback.getCaptchaProvider().getCaptchaType(); + if(currentCaptchaType == CaptchaType.None + || currentCaptchaType == CaptchaType.ThirdParty){ + requestLogin.setUuid(IdUtils.simpleUUID()); + } + + // 娣诲姞token澶辨晥鏃堕棿锛堜粠閰嶇疆鑾峰彇锛夛紝2023-03-28 + long expiredMinutes = SecurityConfigUtils.getTokenExpireMinutes(requestLogin.getClientType(), this.getSecurityProperties()); + String token = TokenUtils.generateToken(userDetails.getUserPrincipal().getId() + , userDetails.getUsername(), requestLogin.getUuid(), this.getTokenGenerator(), expiredMinutes); + logger.debug("token澶辨晥鍒嗛挓:{}", expiredMinutes); +// String token = this.tokenGenerator.createToken(requestLogin.getUuid(), userDetails.getUserPrincipal().getId() +// , VariableConstants.DEFAULT_TOKEN_EXPIRED_MINUTES, VariableConstants.TOKEN_SECRET); + // 缂撳瓨鐧诲綍淇℃伅 + // 2024-01-05 鐧诲綍缂撳瓨锛屽け鏁堟椂闂村簲褰撻暱涓�浜涳紝绯荤粺榛樿30澶┿�傝繖鍜宼oken + long loginCacheExpiredTime = VariableConstants.DEFAULT_TOKEN_EXPIRED_MINUTES; + if(expiredMinutes > loginCacheExpiredTime){ + loginCacheExpiredTime = expiredMinutes; + } + this.getUserOnlineProvider().cacheUserPrincipal(requestLogin.getUuid(), userDetails.getUserPrincipal(), loginCacheExpiredTime); + // 鎶婃垚鍔熺櫥褰曟棩蹇楋紝涓巙uid鍏宠仈淇濆瓨鏀句竴璧凤紝鍦ㄥ紓姝ヤ腑璋冪敤銆�2023-03-23 + this.recordLoginInfo(username, String.valueOf(ResponseCode.SUCCESS.getCode()), "鐧诲綍鎴愬姛" + , userDetails.getUserPrincipal().getUserInfo().getId(), requestLogin.getUuid(), requestLogin.getClientType()); + + // 2023-08-18锛岀櫥褰曟垚鍔熷洖璋� + AfterLoginCallback afterLoginCallback = PlatformCallbackPostProcessor.getCallbackObject(AfterLoginCallback.class); + if(afterLoginCallback != null){ + afterLoginCallback.onSuccess(requestLogin, userDetails.getUserPrincipal()); + } + + // 2023-05-12锛屽姞涓婄敤鎴蜂俊鎭紙鍟嗘埛绯荤粺鐢級 + Map<String, Object> param = new HashMap<>(2); + param.put(com.walker.web.Constants.TOKEN_NAME, token); + param.put(SecurityConstants.KEY_USER_INFO, UserUtils.acquireClientUserInfo(userDetails.getUserPrincipal().getUserInfo(), token)); + param.put(SecurityConstants.KEY_USER_INFO_APP, userDetails.getUserPrincipal()); +// return ResponseValue.success(ResponseValueUtils.acquireOneParam(com.walker.web.Constants.TOKEN_NAME, token)); + return param; + } + + private String validateCaptcha(String code, String uuid, CaptchaProvider<CaptchaResult> captchaProvider){ + if(StringUtils.isEmpty(uuid) || StringUtils.isEmpty(code)){ +// throw new CaptchaException(); + return "璇疯緭鍏ラ獙璇佺爜"; + } + + CaptchaResult captchaResult = new CaptchaResult(); + captchaResult.setUuid(uuid); + captchaResult.setCode(code); + boolean success = captchaProvider.validateCaptcha(captchaResult); + + // 2023-04-07 璋冩暣锛屼娇鐢ㄦ彁渚涜�呭垽鏂獙璇佺爜鏄惁姝g‘銆� + // 2023-06-30 鍙湁鐭俊楠岃瘉鐮佹椂锛屼笉鑳藉垹闄ょ紦瀛樼殑楠岃瘉鐮侊紝鍥犱负瀛樺湪鎵嬫満绔櫥褰曪紙骞跺悓鏃舵敞鍐岋級鎯呭喌锛屼細璋冪敤涓ゆlogin鎿嶄綔銆� + if(captchaProvider.getCaptchaType() != CaptchaType.SmsCode){ + this.getCaptchaCacheProvider().removeCacheData(com.iplatform.base.Constants.CAPTCHA_CODE_PREFIX + uuid);// 鍒犻櫎缂撳瓨鐨勯獙璇佺爜 + } + + if(!success){ + logger.error("楠岃瘉鐮佹牎楠屽け璐�: code = " + code); + return "楠岃瘉鐮侀敊璇�"; + } + + /*String verifyKey = Constants.CAPTCHA_CODE_PREFIX + uuid; + String captchaCode = this.captchaCacheProvider.getCacheData(verifyKey); + if(StringUtils.isEmpty(captchaCode)){ + return "楠岃瘉鐮佷笉瀛樺湪锛屽彲鑳藉凡缁忓け鏁�"; + } + this.captchaCacheProvider.removeCacheData(verifyKey); // 鍒犻櫎缂撳瓨鐨勯獙璇佺爜 + if(!code.equalsIgnoreCase(captchaCode)){ + logger.error("楠岃瘉鐮佹牎楠屽け璐�:" + captchaCode + ", code = " + code); + return "楠岃瘉鐮侀敊璇�"; + }*/ + return null; + } + + private void recordLoginInfo(String loginId, String status, String message, long userId, String uuid, String clientType){ + if(this.getLogProperties().isLoginEnabled()){ + logger.debug("寮傛璁板綍鐧诲綍鏃ュ織锛屽悗缁琛ュ厖:" + status + ", " + message); + AsyncManager.me().execute(this.acquireLoginInfoTask(loginId, status, message, userId, uuid, clientType)); + } + } + + private TimerTask acquireLoginInfoTask(String loginId, String status, String message, Long userId + , String uuid, String clientType){ + HttpServletRequest request = ServletUtils.getRequest(); + final WebUserAgent webUserAgent = this.getWebAgentService().getWebUserAgent(request.getHeader("User-Agent"), request); + + return new TimerTask() { + @Override + public void run() { + S_login_info login_info = new S_login_info(); + login_info.setLogin_time(Long.parseLong(DateUtils.getDateTimeSecondForShow())); + login_info.setUser_name(loginId); + login_info.setMsg(message); + login_info.setStatus(status); + login_info.setInfo_id(NumberGenerator.getLongSequenceNumber()); + if(webUserAgent != null){ + login_info.setLogin_location(webUserAgent.getLocation()); + login_info.setBrowser(webUserAgent.getBrowserName()); + login_info.setIpaddr(webUserAgent.getIp()); + login_info.setOs(webUserAgent.getOsName()); + } + + // 2023-03-23 + if(status.equals(String.valueOf(ResponseCode.SUCCESS.getCode()))){ + S_user_login user_login = null; + if(getLoginStrategyManager().hasUserLogin(loginId)){ + user_login = getLoginService().execUpdateUserLogin(userId, loginId, uuid, clientType, login_info, true); + getLoginStrategyManager().updateUserLoginCache(user_login); + } else { + // 鐧诲綍鎴愬姛鎵嶈褰晆uid鍏宠仈缂撳瓨 + user_login = getLoginService().execUpdateUserLogin(userId, loginId, uuid, clientType, login_info, false); + getLoginStrategyManager().putUserLoginCache(user_login); + } + } else { + // 鐧诲綍澶辫触锛屼粎璁板綍鐧诲綍鏃ュ織 + getLogService().execInsertLoginLog(login_info, userId); + } + } + }; + } + + private AuthenticationManager getAuthenticationManager(){ + return BeanContextAware.getBeanByType(AuthenticationManager.class); + } + private TokenGenerator getTokenGenerator(){ + return BeanContextAware.getBeanByType(TokenGenerator.class); + } + private CacheProvider<String> getCaptchaCacheProvider(){ + return (CacheProvider<String>)BeanContextAware.getBeanByName(BEAN_NAME_CAPTCHA_CACHE); + } + private WebAgentService getWebAgentService(){ + return BeanContextAware.getBeanByType(WebAgentService.class); + } + private UserOnlineProvider getUserOnlineProvider(){ + return BeanContextAware.getBeanByType(UserOnlineProvider.class); + } + private SecurityProperties getSecurityProperties(){ + return BeanContextAware.getBeanByType(SecurityProperties.class); + } + private LogProperties getLogProperties(){ + return BeanContextAware.getBeanByType(LogProperties.class); + } + private LoginServiceImpl getLoginService(){ + return BeanContextAware.getBeanByType(LoginServiceImpl.class); + } + private LogServiceImpl getLogService(){ + return BeanContextAware.getBeanByType(LogServiceImpl.class); + } + private LoginStrategyManager getLoginStrategyManager(){ + return BeanContextAware.getBeanByType(LoginStrategyManager.class); + } + + private static final String BEAN_NAME_CAPTCHA_CACHE = "captchaCacheProvider"; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` + //~ 浠ヤ笂鏄櫥褰曟柟娉曟娊鍙栦唬鐮併��2023-06-28 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` + + @Deprecated + public void loginAsWorkflowRole(){ + DefaultUserDetails userDetails = this.getCurrentUserDetails(); + userDetails.addGrantedAuthority(Constants.ROLE_ACTIVITI_USER); + logger.debug("......loginAsWorkflowRole(), {}", userDetails.getRoleIdList()); + } + + @Override + public List<String> getCurrentUserRoleIdList(){ + DefaultUserDetails userDetails = this.getCurrentUserDetails(); + if(userDetails == null){ + logger.error("鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛閿欒锛歡etCurrentUserDetails() == null"); + return null; + } + return userDetails.getRoleIdList(); + } + + @Override + public UserPrincipal<S_user_core> getCurrentUserPrincipal() { + DefaultUserDetails userDetails = this.getCurrentUserDetails(); + if(userDetails == null){ + logger.error("鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛閿欒锛歡etCurrentUserDetails() == null"); + return null; + } + return userDetails.getUserPrincipal(); + } + + @Override + public S_user_core getCurrentUser() { + UserPrincipal<S_user_core> userPrincipal = this.getCurrentUserPrincipal(); + if(userPrincipal == null){ + throw new WebRuntimeException("褰撳墠鎿嶄綔鏈壘鍒扮櫥褰曚汉鍛�: userPrincipal not found in thread!"); + } + return userPrincipal.getUserInfo(); + } + + @Override + public long getCurrentUserId() { + S_user_core user = this.getCurrentUser(); + return user.getId(); + } + + @Override + public String encryptPassword(String password) { + PasswordEncoder passwordEncoder = BeanContextAware.getBeanByType(PasswordEncoder.class); + return passwordEncoder.encode(password); + } + + @Override + public boolean matchesPassword(String rawPassword, String encodedPassword) { + PasswordEncoder passwordEncoder = BeanContextAware.getBeanByType(PasswordEncoder.class); + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + private DefaultUserDetails getCurrentUserDetails(){ + Authentication authentication = this.getAuthentication(); + if(authentication == null){ + throw new WebRuntimeException("褰撳墠鎿嶄綔鏈壘鍒扮櫥褰曡璇佸璞�: authentication not found in thread!"); + } + Object userDetails = authentication.getPrincipal(); + if(userDetails instanceof DefaultUserDetails){ + return (DefaultUserDetails) userDetails; + } + return null; + } + + /** + * 鑾峰彇Authentication + * @author 鏃跺厠鑻� + * @date 2022-11-10 + */ + private Authentication getAuthentication() { + return SecurityContextHolder.getContext().getAuthentication(); + } + + /** + * 杩斿洖绯荤粺閰嶇疆鍙彉鍙傛暟瀵硅薄銆� + * @param key 鍙傛暟 key + * @return + * @date 2022-11-29 + */ + private Variable getArgumentVariable(String key){ + Variable v = BeanContextAware.getBeanByType(ArgumentsManager.class).getVariable(key); + if(v == null){ + throw new IllegalArgumentException("鍙彉閰嶇疆鍙傛暟涓嶅瓨鍦�: " + key); + } + return v; + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetails.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetails.java new file mode 100644 index 0000000..94ae1c0 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetails.java @@ -0,0 +1,171 @@ +package com.iplatform.security; + +import com.iplatform.model.po.S_user_core; +import com.walker.infrastructure.utils.StringUtils; +import com.walker.web.UserPrincipal; +import com.walker.web.UserType; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Spring Security 瀹氫箟鐨勭敤鎴风粏鑺傚璞★紝鍦ㄨ璇佷互鍙婅繃婊ゆ潈闄愭椂浣跨敤銆� + * @author 鏃跺厠鑻� + * @date 2022-10-31 + */ +public class DefaultUserDetails implements UserDetails { + + private List<GrantedAuthority> grantedList = new ArrayList<GrantedAuthority>(4); + private List<String> roleIdList = new ArrayList<>(4); // 鐢ㄦ埛鍖呭惈瑙掕壊ID闆嗗悎锛屽鍔犲啑浣欑湅鍓嶇鏄惁闇�瑕� + + private UserPrincipal<S_user_core> userPrincipal = null; + + public DefaultUserDetails(UserPrincipal<S_user_core> userPrincipal){ + if(userPrincipal == null){ + throw new IllegalArgumentException("UserPrincipal is required!"); + } + this.userPrincipal = userPrincipal; + } + + public UserPrincipal<S_user_core> getUserPrincipal(){ + return this.userPrincipal; + } + + @Override + public Collection<? extends GrantedAuthority> getAuthorities() { + return this.grantedList; + } + + @Override + public String getPassword() { + return this.userPrincipal.getPassword(); + } + + @Override + public String getUsername() { + return this.userPrincipal.getUserName(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return !this.userPrincipal.isAccountLocked(); + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return this.userPrincipal.isEnabled(); + } + + /** + * 杩斿洖鐢ㄦ埛鍖呭惈鐨勮鑹睮D闆嗗悎銆� + * @return + * @date 2022-11-11 + */ + public List<String> getRoleIdList(){ + return this.roleIdList; + } + + /** + * 鎶婅鑹睮D闆嗗悎涔熷瓨鍏rincipal锛屽洜涓鸿瀵硅薄浼氭斁鍏ョ紦瀛橈紝鑰� UserDetails 涓嶄細銆� + * @date 2022-11-11 + */ + public void setRoleIdListToPrincipal(){ + this.userPrincipal.setRoleIdList(this.roleIdList); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //~ 閬楃暀浠g爜锛岀湅鏄惁鑳界敤涓娿��2022-10-31 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public boolean isSupervisor(){ + return this.userPrincipal.getUserInfo().getUser_type() == UserType.TYPE_SUPER; + } + + private static final Map<String, GrantedAuthority> gas = new HashMap<String, GrantedAuthority>(3); + + public void addGrantedAuthority(String roleName){ +// if(roleName != null +// && (roleName.equals(ROLE_SUPER_ADMIN) || roleName.equals(ROLE_ADMIN) +// || roleName.equals(ROLE_USER))){ +// this.grantedList.add(gas.get(roleName)); +// } + if(StringUtils.isNotEmpty(roleName)){ + GrantedAuthority ga = gas.get(roleName); + if(ga == null){ + ga = new SimpleGrantedAuthority(roleName); + gas.put(roleName, ga); + } + this.grantedList.add(ga); + + // + if(!this.roleIdList.contains(roleName)){ + this.roleIdList.add(roleName); + } + } + } + + public boolean equals(Object o){ + if(o == null) return false; + if(o == this) return true; + if(o instanceof DefaultUserDetails){ + DefaultUserDetails _o = (DefaultUserDetails)o; + if(_o.getUsername().equals(this.getUsername()) + && _o.getPassword().equals(this.getPassword()) + && _o.isEnabled() == this.isEnabled()){ + return true; + } + } + return false; + } + + public int hashCode(){ + int result = 31; + return result + 31*this.getUsername().hashCode() + + this.getPassword().hashCode() + 31*(this.isEnabled() ? 1 : 0); + } + + private String ip; + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + +// private UserDiagram uerDiagram; +// +// /** +// * 杩斿洖鐢ㄦ埛鍏锋湁鐨勮彍鍗曟潈闄愬浘淇℃伅銆� +// * @return +// */ +// public UserDiagram getUerDiagram() { +// return uerDiagram; +// } +// +// public void setUerDiagram(UserDiagram uerDiagram) { +// this.uerDiagram = uerDiagram; +// } + + @Override + public String toString(){ + return new StringBuilder().append("[userDetails, name=").append(this.getUsername()).append("]").toString(); + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetailsService.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetailsService.java new file mode 100644 index 0000000..f9ba7f3 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/DefaultUserDetailsService.java @@ -0,0 +1,209 @@ +package com.iplatform.security; + +import com.iplatform.base.Constants; +import com.iplatform.base.DefaultUserPrincipal; +import com.iplatform.base.SecurityConstants; +import com.iplatform.base.cache.MenuCacheProvider; +import com.iplatform.base.service.UserServiceImpl; +import com.iplatform.base.util.UserUtils; +import com.iplatform.model.po.S_menu; +import com.iplatform.model.po.S_user_core; +import com.iplatform.security.config.SecurityProperties; +import com.walker.infrastructure.utils.PhoneNumberUtils; +import com.walker.infrastructure.utils.StringUtils; +import com.walker.web.UserType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DefaultUserDetailsService implements UserDetailsService { + + protected final transient Logger logger = LoggerFactory.getLogger(getClass()); + + private UserServiceImpl userService = null; + private SecurityProperties securityProperties; + private MenuCacheProvider menuCacheProvider; + + public void setMenuCacheProvider(MenuCacheProvider menuCacheProvider) { + this.menuCacheProvider = menuCacheProvider; + } + + public void setSecurityProperties(SecurityProperties securityProperties) { + this.securityProperties = securityProperties; + } + +// public void setPasswordEncoder(PasswordEncoder passwordEncoder) { +// this.passwordEncoder = passwordEncoder; +// } + + public void setUserService(UserServiceImpl userService) { + this.userService = userService; + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { +// UserPrincipal<S_user_core> userPrincipal = this.acquireUserPrincipal(username); + logger.debug("loadUserByUsername = " + username); + DefaultUserDetails userDetails = this.acquireUserPrincipal(username); + if(userDetails == null) { + throw new UsernameNotFoundException("not found user: " + username); + } + // 琚鐢ㄧ殑鐢ㄦ埛涔熶笉鑳界櫥褰� + if(!userDetails.isEnabled()) { + throw new UsernameNotFoundException("user is forbidden: " + username); + } + + // 楠岃瘉鐢ㄦ埛 + // 2023-01-28 楠岃瘉瀵嗙爜鏀惧湪鐧诲綍鍥炶皟涓�� +// this.validateUserInfo(userDetails.getUserPrincipal()); + return userDetails; + } + + /*private void validateUserInfo(UserPrincipal<S_user_core> userPrincipal){ + // 2023-01-26 閫氳繃 PlatformLoginCallback 鏉ユ牎楠屽瘑鐮併�� + PlatformLoginCallback loginCallback = LoginCallbackUtils.getLoginCallbackBean(UserType.getType(userPrincipal.getUserInfo().getUser_type())); + if(loginCallback == null){ + throw new ApplicationRuntimeException("鏈壘鍒�: loginCallback, userType = " + userPrincipal.getUserInfo().getUser_type()); + } + boolean success = loginCallback.validatePassword(userPrincipal); + if(!success){ + throw new BadCredentialsException(ResponseCode.USER_CREDENTIALS_ERROR.getMessage()); + } +// Authentication usernamePasswordAuthenticationToken = SecurityContextHolder.getContext().getAuthentication(); +// String password = usernamePasswordAuthenticationToken.getCredentials().toString(); +// if(!this.passwordEncoder.matches(password, userPrincipal.getPassword())){ +// throw new BadCredentialsException(ResponseCode.USER_CREDENTIALS_ERROR.getMessage()); +// } + logger.debug("娓呯┖蹇呰鐨勭紦瀛�:鎴栨洿鏂扮櫥褰曠紦瀛�"); + }*/ + + public DefaultUserDetails acquireUserPrincipal(String loginId){ + if(StringUtils.isEmpty(loginId)){ + return null; + } + + DefaultUserPrincipal userPrincipal = null; + + // 濡傛灉瓒呯骇绠$悊鍛橈紝涓嶈兘鏌ユ暟鎹簱锛岀洿鎺ュ垱寤哄璞°��2022-11-06 + if(loginId.equals(Constants.SUPERVISOR_NAME_DEFAULT)){ + userPrincipal = (DefaultUserPrincipal) UserUtils.createSupervisor(this.securityProperties.getSupervisorPassword()); + DefaultUserDetails userDetails = new DefaultUserDetails(userPrincipal); + // 2022-12-02 + userDetails.addGrantedAuthority(SecurityConstants.ROLE_SUPER_ADMIN); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_ADMIN); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_USER); +// userDetails.addGrantedAuthority(com.walker.web.Constants.ROLE_ACTIVITI_USER); + userDetails.setRoleIdListToPrincipal(); + return userDetails; + } + + // 2023-06-28 鏍规嵁鐧诲綍璐﹀彿鏄惁鎵嬫満鍙凤紝鏀寔绉诲姩绔拰PC绔墜鏈虹櫥褰曟柟寮忋�� + boolean isPhoneNumber = PhoneNumberUtils.isCellPhoneNumber(loginId); + Object[] userInfo = null; + if(isPhoneNumber && !this.securityProperties.isUserNameIsPhone()){ + // 閫氳繃鎵嬫満鍙峰瓧娈垫煡璇㈢敤鎴� + userInfo = this.userService.queryLoginUser(loginId, true); + } else { + // 閫氳繃鐢ㄦ埛鍚嶈嚜鍔ㄦ煡璇㈢敤鎴� + userInfo = this.userService.queryLoginUser(loginId, false); + } + + if(userInfo == null){ + logger.debug("鐢ㄦ埛涓嶅瓨鍦�: " + loginId); + return null; + } + S_user_core user = (S_user_core) userInfo[0]; // 鐢ㄦ埛淇℃伅涓�瀹氬瓨鍦� + List<String> roleIdList = (List<String>)userInfo[1];// 瑙掕壊ID闆嗗悎锛屼笉涓�瀹氬瓨鍦� + logger.debug("鎵惧埌鐢ㄦ埛: " + user.getUser_name()); + + // 鍔犲叆鏅�氱敤鎴峰叿鏈夌殑瑙掕壊ID锛屾潈闄愭牴鎹鑹睮D鍒ゆ柇 + userPrincipal = new DefaultUserPrincipal(user); + // 璁剧疆鐧诲綍鏃堕棿锛屽悗闈㈣璁$畻杩囨湡锛�2022-11-14 + userPrincipal.setLastLoginTime(System.currentTimeMillis()); + DefaultUserDetails userDetails = new DefaultUserDetails(userPrincipal); + if(roleIdList != null){ + for(String roleId : roleIdList){ + userDetails.addGrantedAuthority(roleId); + } + } + + // 2022-12-21锛岀敤鎴锋暟鎹潈闄� ========================= + // 2023-07-17锛岀敱浜巓racle鏌ヨ鎶ラ敊锛坕n (:roleIds)锛�,鏆傛椂鍏抽棴鏁版嵁鏉冮檺鏌ヨ +// Map<String, String> dataScopeMap = this.acquireUserDataScopeList(roleIdList); +// if(dataScopeMap != null){ +// logger.debug("鐢ㄦ埛鏁版嵁鏉冮檺闆嗗悎 = " + dataScopeMap); +// userPrincipal.setDataScopeMap(dataScopeMap); +// } + // ================================================ + + // 2022-11-15 + int userType = userDetails.getUserPrincipal().getUserInfo().getUser_type(); + + /* 璁剧疆鐢ㄦ埛鐨勮鑹茬被鍨� */ + if(userType == UserType.TYPE_SUPER){ + userDetails.addGrantedAuthority(SecurityConstants.ROLE_SUPER_ADMIN); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_ADMIN); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_USER); + + } else if(userType == UserType.TYPE_ADMIN || userType == UserType.TYPE_ADMIN_DEPT){ + userDetails.addGrantedAuthority(SecurityConstants.ROLE_ADMIN); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_USER); + +// } else if(userType == UserType.TYPE_NORMAL || userType == UserType.TYPE_APP_REG){ + } else if(userType == UserType.TYPE_NORMAL){ + userDetails.addGrantedAuthority(SecurityConstants.ROLE_USER); + + } else if(userType == UserType.TYPE_APP_REG){ + // 2023-01-27 app娉ㄥ唽鐢ㄦ埛锛屼笉缁欎换浣曡鑹叉潈闄� + // 2023-03-20 app娉ㄥ唽鐢ㄦ埛锛岄渶瑕佺粰'ROLE_USER'锛屽洜涓鸿繕闇�瑕佽闂叕鍏辨潈闄愶紙鐧诲綍鍚庨兘鑳界湅鐨勫锛�/permit/**,/getInfo锛夛紝浣嗕笉缁欎换浣曡鑹诧紒 + userDetails.addGrantedAuthority(SecurityConstants.ROLE_USER); + + } else if(userType == UserType.TYPE_MERCHANT_ADMIN){ + // 2023-06-06 鍟嗘埛绠$悊鍛橈紙娉涙寚鐙珛涓氬姟鍗曚綅鐨勶細鍗曚綅绠$悊鍛橈級 + userDetails.addGrantedAuthority(SecurityConstants.ROLE_MERCHANT); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_USER); + + } else + throw new IllegalArgumentException("unknown user type: " + userType); + + // 娣诲姞宸ヤ綔娴佽鑹诧紝鍚﹀垯activiti7鑰佹姤閿�'鏃犳潈闄�'锛�2023-03-21 +// userDetails.addGrantedAuthority(com.walker.web.Constants.ROLE_ACTIVITI_USER); + // + userDetails.setRoleIdListToPrincipal(); + + return userDetails; + } + + /** + * 鐢变簬oracle鏌ヨ鎶ラ敊锛坕n (:roleIds)锛�,鏆傛椂鍏抽棴鏁版嵁鏉冮檺鏌ヨ + * @param roleIdList + * @return + * @date 2023-07-17 + */ + @Deprecated + private Map<String, String> acquireUserDataScopeList(List<String> roleIdList){ + if(StringUtils.isEmptyList(roleIdList)){ + return null; + } + List<String> dataScopeMenuIdList = this.userService.queryUserDataScopeMenuIdList(roleIdList); + if(StringUtils.isEmptyList(dataScopeMenuIdList)){ + return null; + } + Map<String, String> dataScopeMap = new HashMap<>(8); + S_menu menu = null; + for(String menuId : dataScopeMenuIdList){ + menu = this.menuCacheProvider.getCacheData(menuId); + if(menu == null){ + throw new IllegalStateException("鑿滃崟缂撳瓨涓嶅瓨鍦�:" + menuId); + } + dataScopeMap.put(menu.getParent_id(), menuId.replaceFirst(Constants.DATA_SCOPE_NAME, StringUtils.EMPTY_STRING)); + } + return dataScopeMap; + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/FailedAuthenticationEntryPoint.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/FailedAuthenticationEntryPoint.java new file mode 100644 index 0000000..3b627df --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/FailedAuthenticationEntryPoint.java @@ -0,0 +1,36 @@ +package com.iplatform.security; + +import com.walker.infrastructure.utils.JsonUtils; +import com.walker.web.ResponseCode; +import com.walker.web.ResponseValue; +import com.walker.web.util.ServletUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import javax.servlet.ServletException; +import java.io.IOException; + +/** + * 鍖垮悕鐢ㄦ埛璁块棶鏃犳潈闄愯祫婧愭椂鐨勫紓甯搞�� + * @author 鏃跺厠鑻� + * @date 2022-10-31 + */ +public class FailedAuthenticationEntryPoint implements AuthenticationEntryPoint { + + protected final transient Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public void commence(javax.servlet.http.HttpServletRequest request + , javax.servlet.http.HttpServletResponse response + , AuthenticationException authException) throws IOException, ServletException { + + String msg = "璁よ瘉澶辫触锛屾棤鏉冮檺璁块棶绯荤粺璧勬簮" + request.getRequestURI(); + try { + ServletUtils.renderString(response, JsonUtils.objectToJsonString(ResponseValue.error(ResponseCode.EXCEPTION.getCode(), msg))); + } catch (Exception e) { + logger.error("鏃犳潈闄愯闂郴缁熻祫婧�" + request.getRequestURI()); + } + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/JwtAuthenticationTokenFilter.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..241bb83 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/JwtAuthenticationTokenFilter.java @@ -0,0 +1,195 @@ +package com.iplatform.security; + +import com.iplatform.base.DefaultUserPrincipal; +import com.iplatform.base.SecurityConstants; +import com.iplatform.base.VariableConstants; +import com.iplatform.base.util.TokenUtils; +import com.iplatform.core.TokenAwareContext; +import com.iplatform.core.TokenEntity; +import com.iplatform.model.po.S_user_core; +import com.iplatform.security.config.SecurityProperties; +import com.walker.infrastructure.ApplicationRuntimeException; +import com.walker.web.Constants; +import com.walker.web.ResponseCode; +import com.walker.web.ResponseValue; +import com.walker.web.TokenException; +import com.walker.web.TokenGenerator; +import com.walker.web.UserOnlineProvider; +import com.walker.web.UserPrincipal; +import com.walker.web.util.ServletUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + protected final transient Logger logger = LoggerFactory.getLogger(getClass()); + + private TokenGenerator tokenGenerator; + private UserOnlineProvider userOnlineProvider; + private DefaultUserDetailsService defaultUserDetailsService; + + // 2023-03-28 + private SecurityProperties securityProperties; + + public void setSecurityProperties(SecurityProperties securityProperties) { + this.securityProperties = securityProperties; + } + + public void setDefaultUserDetailsService(DefaultUserDetailsService defaultUserDetailsService) { + this.defaultUserDetailsService = defaultUserDetailsService; + } + + public void setUserOnlineProvider(UserOnlineProvider userOnlineProvider) { + this.userOnlineProvider = userOnlineProvider; + } + + public void setTokenGenerator(TokenGenerator tokenGenerator) { + this.tokenGenerator = tokenGenerator; + } + + @Override + protected void doFilterInternal(HttpServletRequest request + , HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + + String token = TokenUtils.getAuthorizationToken(request); + if(token != null){ + try{ + String data = tokenGenerator.validateToken(token, VariableConstants.TOKEN_SECRET); + logger.debug("token_data = " + data); + String[] userIdAndKey = TokenUtils.getUserIdAndKey(data); + if(userIdAndKey == null || userIdAndKey.length != 3){ + throw new ApplicationRuntimeException("token鎼哄甫鐢ㄦ埛淇℃伅瑙f瀽閿欒:" + data); + } + + String uuid = userIdAndKey[2]; + String loginId = userIdAndKey[1]; + DefaultUserDetails userDetails = null; + + // 鏍规嵁token鑾峰彇鐢ㄦ埛瀵硅薄 + DefaultUserPrincipal userPrincipal = this.acquireAuthenticationUser(uuid); + if(userPrincipal == null){ + // 2022-11-15锛岃繖閲岃鍛婅瘔瀹㈡埛绔埛鏂皌oken + // redis涓紦瀛樼櫥褰曟椂闂村簲灏忎簬token澶辨晥鏃堕棿 + userDetails = this.defaultUserDetailsService.acquireUserPrincipal(loginId); + + // 2023-09-03 褰撳墠绔紶鍏ョ殑 token 鏄棤鏁堢殑鎯呭喌涓嬶紝濡傦細鐢ㄦ埛宸蹭笉瀛樺湪锛岄渶瑕佸垹闄ょ櫥褰曠紦瀛� + if(userDetails == null){ + this.userOnlineProvider.removeUserPrincipal(uuid); + this.logger.warn("鐢ㄦ埛宸蹭笉瀛樺湪锛屽垹闄ょ櫥褰曠姸鎬佺紦瀛橈細{}", uuid); + return; + } + + userPrincipal = (DefaultUserPrincipal)userDetails.getUserPrincipal(); + logger.debug("token闇�瑕佸埛鏂�: " + userPrincipal.getUserName()); + this.tellClientRefreshToken(response, uuid, userPrincipal); + // 2022-11-15锛屼互涓嬪搷搴斾唬鐮佷笉鍐嶉渶瑕侊紝鍥犱负宸茬粡鍒锋柊token锛岄噸鏂扮紦瀛樼櫥褰曠敤鎴凤紝 +// ServletUtils.renderString(response, ResponseValue.error(ResponseCode.RE_LOGIN.getCode(), "token涓嶅瓨鍦ㄦ垨宸茶繃鏈燂紝璇烽噸鏂拌璇�")); +// return; + } else { + userDetails = this.acquireUserDetails(userPrincipal); + } + + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + + // 2023-08-05 + TokenAwareContext.setCurrentToken(new TokenEntity(uuid, loginId)); + + } catch (TokenException ex){ + if(ex.isExpired()){ + ServletUtils.renderString(response, ResponseValue.error(ResponseCode.RE_LOGIN.getCode(), "token宸茶繃鏈燂紝璇烽噸鏂拌幏鍙�")); + return; + } + System.out.println(ex.getTitle()); + ServletUtils.renderString(response, ResponseValue.error(ResponseCode.ERROR.getCode(), ex.getTitle())); + return; + + } catch (Exception ex){ + logger.error("鏍规嵁token鑾峰緱鐧诲綍淇℃伅閿欒:" + ex.getMessage(), ex); + ServletUtils.renderString(response, ResponseValue.error(ResponseCode.ERROR.getCode(), ex.getMessage())); + return; + } + } + // 瑕佸皾璇曪細token涓嶅瓨鍦ㄤ笉鑳借闂� +// logger.warn("token涓嶅瓨鍦紝鏃犳硶璁块棶绯荤粺鏇磋兘"); + filterChain.doFilter(request, response); + // 2023-08-05 + TokenAwareContext.clearCurrentToken(); + } + + /** + * 閫氱煡缁堢鍒锋柊token锛宼oken浼氬啓鍏ュ搷搴斿ご涓�: TokenRefresh 瀛楁銆� + * @param response + * @param uuid + * @param userPrincipal + */ + private void tellClientRefreshToken(HttpServletResponse response, String uuid, DefaultUserPrincipal userPrincipal){ +// String token = this.tokenGenerator.createToken(uuid, userPrincipal.getId() +// , VariableConstants.DEFAULT_TOKEN_EXPIRED_MINUTES, VariableConstants.TOKEN_SECRET); + // 鍒锋柊token锛岄�氬父PC绔細鐢ㄥ埌锛岀Щ鍔ㄧ鏃堕棿闀夸娇鐢ㄥ嚑鐜囦綆锛屽洜姝よ繖閲屾壘PC绔厤缃��2023-03-28 + String token = TokenUtils.generateToken(userPrincipal.getId() + , userPrincipal.getUserName(), uuid, this.tokenGenerator, securityProperties.getTokenExpireWeb()); + // 閲嶆柊璁剧疆鐢ㄦ埛鍒涘缓token鏃堕棿 + userPrincipal.setLastLoginTime(System.currentTimeMillis()); + this.userOnlineProvider.cacheUserPrincipal(uuid, userPrincipal, securityProperties.getTokenExpireWeb()); + response.addHeader(Constants.TOKEN_HEADER_REFRESH, token); + if(this.logger.isDebugEnabled()){ + logger.debug("鍒锋柊token, uuid = " + uuid + ", " + token); + } + } + + private DefaultUserDetails acquireUserDetails(UserPrincipal<S_user_core> userPrincipal){ + DefaultUserDetails userDetails = new DefaultUserDetails(userPrincipal); +// if(userPrincipal.getUserInfo().isSupervisor()){ + if(userDetails.isSupervisor()){ + userDetails.addGrantedAuthority(SecurityConstants.ROLE_SUPER_ADMIN); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_ADMIN); + userDetails.addGrantedAuthority(SecurityConstants.ROLE_USER); + } else { + // 褰撳墠鏁版嵁搴撳彧鏈変竴涓櫘閫氳鑹�:2 +// userDetails.addGrantedAuthority("2"); + // 鍦ㄧ敤鎴风櫥褰曞悗锛岀紦瀛樼殑灏辨湁瑙掕壊ID闆嗗悎锛岃繖閲屾瘡娆¤闂噸鏂拌缃埌瀵硅薄涓��2022-11-11 + List<String> roleIdList = userPrincipal.getRoleIdList(); + logger.info("缂撳瓨涓幏鍙� userPrincipal.getRoleIdList() = " + roleIdList); + if(roleIdList != null){ + for(String roleId : roleIdList){ + userDetails.addGrantedAuthority(roleId); + } + } + } + return userDetails; + } + + /** + * 妯℃嫙娴嬭瘯锛屽悗缁慨鏀逛负鏁版嵁搴撴柟寮忋��<p></p> + * 浠庣紦瀛樹腑璇诲彇鐢ㄦ埛鐧诲綍淇℃伅锛屽鏋滄崲鎴愬け鏁堜负绌恒�� + * @param uuid + * @return + * @date 2022-11-15 + */ + private DefaultUserPrincipal acquireAuthenticationUser(String uuid){ + /*String userId = userIdAndKey[0]; + if(userId.equals("0")){ + // 0 涓鸿秴绾х鐞嗗憳 + return MockPrincipalUtils.createSupervisor(); + } else { + // 鍏朵粬鍊兼ā鎷熶负鏅�氱敤鎴� + return MockPrincipalUtils.createNormalUser("100"); + }*/ + // uuid +// String loginKey = userIdAndKey[2]; + return (DefaultUserPrincipal)this.userOnlineProvider.getUserPrincipal(uuid); + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/EncryptPasswordLoginCallback.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/EncryptPasswordLoginCallback.java new file mode 100644 index 0000000..f9cc0f1 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/EncryptPasswordLoginCallback.java @@ -0,0 +1,57 @@ +package com.iplatform.security.callback; + +import com.iplatform.base.util.PlatformRSAUtils; +import com.iplatform.model.po.S_user_core; +import com.walker.web.CaptchaType; +import com.walker.web.UserPrincipal; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * 绉诲姩绔�氳繃锛氳处鍙枫�佸瘑鐮佹柟寮忕櫥褰曪紝<br> + * 涓嶉渶瑕佷换浣曢獙璇佺爜銆� + * @author 鏃跺厠鑻� + * @date 2023-03-20 + * @date 2023-04-07 淇敼鍚嶅瓧涓�'瀵嗙爜鍔犲瘑'鐧诲綍鍥炶皟瀹炵幇銆� + */ +public class EncryptPasswordLoginCallback extends +// GeneralLoginCallback + SimplePasswordLoginCallback +{ + +// @Deprecated +// @Override +// public Object[] queryLoginUser(String loginId) { +// return new Object[0]; +// } + + @Override + public boolean validatePassword(UserPrincipal<S_user_core> userPrincipal) { + Authentication usernamePasswordAuthenticationToken = SecurityContextHolder.getContext().getAuthentication(); + String password = usernamePasswordAuthenticationToken.getCredentials().toString(); + try { + // APP浼犺繃鏉ョ殑瀵嗙爜鏄疪SA鍔犲瘑鍐呭銆� +// byte[] data = RSAUtil.decryptByPrivateKey(password.getBytes(StandardCharsets.UTF_8), PRIK); +// String pass = new String(data); + // 2023-06-30 鐩墠鐢靛晢绉诲姩绔櫥褰曪細鎵嬫満鍙� + 瀵嗙爜锛屼娇鐢ㄧ殑鏄槑鏂囧瘑鐮侊紝鍚庣画瑕佹敼鎴愪竴鑷淬�� + String originPassword = null; + if(this.getCaptchaProvider().getCaptchaType() == CaptchaType.None){ +// originPassword = password; + // 2023-08-06 uniapp绔娇鐢ㄥ绉板瘑鐮佺畻娉� + originPassword = PlatformRSAUtils.getAesDecryptValue(password); + } else { + originPassword = PlatformRSAUtils.getRsaDecryptValue(password, PlatformRSAUtils.PRIK); + } + logger.debug("......... 瑙e瘑鐨刾assword = {}", originPassword); + return this.passwordEncoder.matches(originPassword, userPrincipal.getPassword()); + } catch (Exception e) { + logger.error("", e); + throw new RuntimeException("瑙f瀽鐧诲綍瀵嗙爜閿欒:" + e.getMessage(), e); + } + } + +// public void setPasswordEncoder(PasswordEncoder passwordEncoder) { +// this.passwordEncoder = passwordEncoder; +// } +// private PasswordEncoder passwordEncoder = null; +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/MobilePassCaptchaLoginCallback.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/MobilePassCaptchaLoginCallback.java new file mode 100644 index 0000000..2f1da05 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/MobilePassCaptchaLoginCallback.java @@ -0,0 +1,31 @@ +package com.iplatform.security.callback; + +import com.iplatform.base.util.PlatformRSAUtils; +import com.iplatform.model.po.S_user_core; +import com.walker.web.UserPrincipal; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * 绉诲姩绔紙H5锛夛紝浣跨敤锛氱敤鎴峰悕銆佸瘑鐮侊紙AES锛� + 鏅�氶獙璇佺爜鐧诲綍鏂瑰紡銆� + * <p>鍥犱负绉诲姩绔笌PC绔瘑鐮佸姞瀵嗘柟寮忎笉涓�鑷达紝鎵�浠ユ棤娉曞鐢≒C鐧诲綍楠岃瘉妯″紡锛屽洜姝ら噸鏂板畾涔夛紒</p> + * @author 鏃跺厠鑻� + * @date 2023-12-28 + */ +public class MobilePassCaptchaLoginCallback extends EncryptPasswordLoginCallback{ + + @Override + public boolean validatePassword(UserPrincipal<S_user_core> userPrincipal) { + Authentication usernamePasswordAuthenticationToken = SecurityContextHolder.getContext().getAuthentication(); + String password = usernamePasswordAuthenticationToken.getCredentials().toString(); + try { + // 绉诲姩绔紝鍙敮鎸丄ES瀵嗙爜鍔犲瘑锛岀洰鍓嶆儏鍐点��2023-12-28 + String originPassword = PlatformRSAUtils.getAesDecryptValue(password); + logger.debug("......... 瑙e瘑鐨刾assword = {}", originPassword); + return this.passwordEncoder.matches(originPassword, userPrincipal.getPassword()); + } catch (Exception e) { + logger.error("", e); + throw new RuntimeException("瑙f瀽鐧诲綍瀵嗙爜閿欒:" + e.getMessage(), e); + } + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/NoneCaptchaLoginCallback.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/NoneCaptchaLoginCallback.java new file mode 100644 index 0000000..a58e76e --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/NoneCaptchaLoginCallback.java @@ -0,0 +1,11 @@ +package com.iplatform.security.callback; + +/** + * 涓嶅甫楠岃瘉鐮佺被鍨嬬殑锛堣处鎴枫�佸瘑鐮侊級鐧诲綍鏂瑰紡鎵╁睍銆� + * <p>浠呬负浜嗗畾涔変竴绉嶇被鍨嬶紝娌℃湁浠讳綍浠g爜鍙噸鍐�</p> + * @author 鏃跺厠鑻� + * @date 2023-04-07 + */ +public class NoneCaptchaLoginCallback extends EncryptPasswordLoginCallback{ + +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SimplePasswordLoginCallback.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SimplePasswordLoginCallback.java new file mode 100644 index 0000000..66f86f8 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SimplePasswordLoginCallback.java @@ -0,0 +1,39 @@ +package com.iplatform.security.callback; + +import com.iplatform.base.callback.GeneralLoginCallback; +import com.iplatform.model.po.S_user_core; +import com.walker.web.UserPrincipal; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * <s>PC绔綉椤电櫥褰曞洖璋冨疄鐜般��</s><p></p> + * 鐢ㄦ埛鍚嶅瘑鐮佺櫥褰曟柟寮忓洖璋冨疄鐜般�� + * @author 鏃跺厠鑻� + * @date 2023-01-26 + * @date 2023-01-28 鐢ㄦ埛鍚嶃�佸瘑鐮佹柟寮忕櫥褰曠殑鍥炶皟瀹炵幇銆� + * @date 2023-04-07 閲嶆瀯鍚嶅瓧涓�'鏄庢枃瀵嗙爜'鐧诲綍鍥炶皟瀹炵幇銆傚弬鑰冿細{@linkplain EncryptPasswordLoginCallback} + */ +public class SimplePasswordLoginCallback extends GeneralLoginCallback { + + @Deprecated + @Override + public Object[] queryLoginUser(String loginId) { + return this.userService.queryLoginUser(loginId, false); + } + + @Override + public boolean validatePassword(UserPrincipal<S_user_core> userPrincipal) { + Authentication usernamePasswordAuthenticationToken = SecurityContextHolder.getContext().getAuthentication(); + String password = usernamePasswordAuthenticationToken.getCredentials().toString(); + logger.debug("鐢ㄦ埛杈撳叆锛�" + password + ", " + userPrincipal.getPassword()); + return this.passwordEncoder.matches(password, userPrincipal.getPassword()); + } + + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + + protected PasswordEncoder passwordEncoder = null; +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SmsCodeLoginCallback.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SmsCodeLoginCallback.java new file mode 100644 index 0000000..246df52 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/SmsCodeLoginCallback.java @@ -0,0 +1,76 @@ +package com.iplatform.security.callback; + +import com.iplatform.base.Constants; +import com.iplatform.base.callback.GeneralLoginCallback; +import com.iplatform.model.po.S_user_core; +import com.walker.cache.CacheProvider; +import com.walker.web.UserPrincipal; + +/** + * APP鏂瑰紡鐧诲綍鍥炶皟瀹炵幇銆� + * @author 鏃跺厠鑻� + * @date 2023-01-26 + * @date 2023-01-28 鐭俊楠岃瘉鐮佺櫥褰曟柟寮忓洖璋� + */ +public class SmsCodeLoginCallback extends GeneralLoginCallback { + + /** + * 閲嶅啓鏂规硶锛岀煭淇¢獙璇佺爜鐧诲綍锛岄渶瑕侀鍏堥獙璇併�傚惁鍒欏湪绉诲姩绔紙鐗瑰埆鏄敤鎴蜂笉瀛樺湪锛岃繕娌℃敞鍐屾儏鍐典笅锛夌洿鎺ヨ烦杩囧苟璋冪敤鎺ュ彛銆� + * @return + * @date 2023-06-30 + */ + @Override + public boolean isValidateCaptcha() { + /*APP鐧诲綍鎻愪氦涓嶉渶瑕佷娇鐢ㄩ獙璇佺爜锛屼粎鍦ㄦ帴鏀剁煭淇℃椂浣跨敤 + 鐭俊楠岃瘉鐮佷綔涓哄瘑鐮佷娇鐢紝鎵�浠ユ病鏈夐獙璇佺爜浜�!*/ + return true; + } + + /** + * 鏆傛湭浣跨敤鍒拌鏂规硶锛岀湅鍚庣画鎯呭喌銆� + * @param loginId + * @return + */ + @Deprecated + @Override + public Object[] queryLoginUser(String loginId) { + Object[] userInfo = new Object[2]; + S_user_core userCore = this.userService.queryLoginUserOnly(loginId); + userInfo[0] = userCore; + userInfo[1] = null; + return userInfo; + } + + /** + * 楠岃瘉瀵嗙爜瀹炵幇銆� + * @param userPrincipal + * @return + * @date 2023-06-30 閲嶆柊淇敼锛岀敱浜庣煭淇¢獙璇佺爜浠嶇劧蹇呴』鎻愬墠鏍¢獙锛屾墍浠ョ幇鍦ㄨ繖閲屽氨鏃犻渶浣滀负瀵嗙爜銆� + */ + @Override + public boolean validatePassword(UserPrincipal<S_user_core> userPrincipal) { +// logger.warn("App鐧诲綍瀵嗙爜楠岃瘉: 鍙兘鏄煭淇℃垨鑰呭瘑鐮侊紝鏍规嵁涓氬姟鎯呭喌瀹炵幇锛岃繖閲�'榛樿楠岃瘉閫氳繃'"); + /*DefaultAuthenticationToken authenticationToken = (DefaultAuthenticationToken)SecurityContextHolder.getContext().getAuthentication(); + RequestLogin requestLogin = authenticationToken.getRequestLogin(); + String smsCode = this.getSmsCode(requestLogin.getUuid()); + if(StringUtils.isNotEmpty(smsCode) && requestLogin.getPassword().equals(smsCode)){ + logger.debug("app楠岃瘉瀵嗙爜鎴愬姛锛宻msCode={}, password={}", smsCode, requestLogin.getPassword()); + return true; + } + logger.error("app鐧诲綍楠岃瘉鐮侀敊璇紝smsCode = " + smsCode + ", inputPass = " + requestLogin.getPassword()); + return false;*/ + return true; + } + + private String getSmsCode(String uuid){ + String verifyKey = Constants.CAPTCHA_CODE_PREFIX + uuid; + // 缂撳瓨涓幏鍙栦箣鍓嶇敓鎴愮殑鐭俊楠岃瘉鐮� + return this.captchaCacheProvider.getCacheData(verifyKey); + } + + public void setCaptchaCacheProvider(CacheProvider<String> captchaCacheProvider) { + this.captchaCacheProvider = captchaCacheProvider; + } + + private CacheProvider<String> captchaCacheProvider; +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/ThirdPartyLoginCallback.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/ThirdPartyLoginCallback.java new file mode 100644 index 0000000..1645c28 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/ThirdPartyLoginCallback.java @@ -0,0 +1,33 @@ +package com.iplatform.security.callback; + +import com.iplatform.model.po.S_user_core; +import com.walker.web.UserPrincipal; + +/** + * 绗笁鏂瑰鎺ョ櫥褰曞洖璋冨疄鐜般�� + * <pre> + * 1)璇ュ疄鐜扮洰鍓嶄粎涓洪绠椾竴浣撳寲瀵规帴瀹為獙鐢紝鍏蜂綋闇�瑕佺湅鍚庨潰鏇村鎯呭喌銆� + * 2)瀵规帴鏃犻渶楠岃瘉鐮侊紝骞朵笖閲囩敤瀵嗙爜鏄庢枃鏂瑰紡锛屽洜涓洪兘鏄悗鍙版搷浣滐紝涓嶅瓨鍦ㄩ闄┿�� + * </pre> + * @author 鏃跺厠鑻� + * @date 2023-07-03 + */ +public class ThirdPartyLoginCallback extends SimplePasswordLoginCallback{ + + @Override + public boolean isValidateCaptcha() { + // 绗笁鏂瑰鎺ワ紝鏃犻獙璇佺爜銆傛殏鏃朵负棰勭畻涓�浣撳寲瀵规帴浣跨敤銆� + return false; + } + + /** + * 绗笁鏂癸紙鏃犻渶锛夐獙璇佸瘑鐮併�� + * @param userPrincipal + * @return + * @date 2023-10-23 鏂版坊鍔犳柟娉曪紝閲嶅啓楠岃瘉瀵嗙爜锛岀敱浜庣涓夋柟浼氱粰鎴戜滑鐢ㄦ埛淇℃伅锛岃繖閲屼竴鑸笉闇�瑕侀獙璇佸瘑鐮併�� + */ + @Override + public boolean validatePassword(UserPrincipal<S_user_core> userPrincipal) { + return true; + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/WechatLoginCallback.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/WechatLoginCallback.java new file mode 100644 index 0000000..2d72dbe --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/callback/WechatLoginCallback.java @@ -0,0 +1,34 @@ +package com.iplatform.security.callback; + +import com.iplatform.model.po.S_user_core; +import com.walker.web.UserPrincipal; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * 寰俊鎺堟潈鐧诲綍锛岀洰鍓嶅叕浼楀彿H5鑷姩鐧诲綍浣跨敤銆� + * <pre> + * 1)鍓嶇澶勭悊寰俊瀵规帴鑾峰彇accessToken; + * 2)璋冪敤鍚庡彴鎺ュ彛鐧诲綍锛屽悗鍙扮粍缁囧弬鏁帮紝瀵嗙爜浠庢暟鎹簱鏌ヨ鍑烘潵锛� + * 3)鍥犳瀵嗙爜鐩存帴灏辨槸鍔犲瘑鐨勶紝鐩存帴姣斿灏辫锛堢浉绛夌殑锛� + * </pre> + * @author 鏃跺厠鑻� + * @date 2023-07-27 + */ +public class WechatLoginCallback extends SimplePasswordLoginCallback{ + + @Override + public boolean validatePassword(UserPrincipal<S_user_core> userPrincipal) { + Authentication usernamePasswordAuthenticationToken = SecurityContextHolder.getContext().getAuthentication(); + String password = usernamePasswordAuthenticationToken.getCredentials().toString(); + logger.debug("鐢ㄦ埛杈撳叆锛�" + password + ", " + userPrincipal.getPassword()); + // 寰俊鐧诲綍锛屼紶杩囨潵鐨勫瘑鐮佸氨鏄暟鎹簱涓煡璇㈢殑锛屽洜涓哄悗鍙颁唬鐮佽皟鐢ㄧ櫥褰曪紒 + return password.equals(userPrincipal.getPassword()); + } + + @Override + public boolean isValidateCaptcha() { + // 鏃犻獙璇佺爜銆� + return false; + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/config/SecurityProperties.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/config/SecurityProperties.java new file mode 100644 index 0000000..c481aa6 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/config/SecurityProperties.java @@ -0,0 +1,172 @@ +package com.iplatform.security.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +@ConfigurationProperties(prefix = "iplatform.security") +public class SecurityProperties { + + private List<String> anonymousList = null; + + private List<String> permitList = null; + + private String supervisorPassword = null; + + private boolean corsEnabled = false; + + private boolean allowPcUserAccessApp = true; + + private long tokenExpireWeb = 120; // PC绔粯璁�2灏忔椂 + private long tokenExpireMobile = 60 * 24 * 15; // 绉诲姩绔粯璁�15澶� + + // 鏀寔鎵嬫満鐧诲綍鏃惰嚜鍔ㄦ敞鍐岋紙鎵嬫満涓嶅瓨鍦ㄥ垯锛岀洿鎺ユ敞鍐岋級 + private boolean allowMobileLoginReg = false; + + private boolean userNameIsPhone = false; + + /** + * 鐢ㄦ埛浣撶郴锛堢敤鎴峰悕锛夐兘鏄墜鏈哄彿銆� + * @return + * @date 2023-06-28 + */ + public boolean isUserNameIsPhone() { + return userNameIsPhone; + } + + public void setUserNameIsPhone(boolean userNameIsPhone) { + this.userNameIsPhone = userNameIsPhone; + } + + /** + * 鏀寔鎵嬫満鐧诲綍鏃惰嚜鍔ㄦ敞鍐岋紙鎵嬫満涓嶅瓨鍦ㄥ垯锛岀洿鎺ユ敞鍐岋級 + * @return + * @date 2023-06-28 + */ + public boolean isAllowMobileLoginReg() { + return allowMobileLoginReg; + } + + public void setAllowMobileLoginReg(boolean allowMobileLoginReg) { + this.allowMobileLoginReg = allowMobileLoginReg; + } + + /** + * 杩斿洖PC绔痶oken澶辨晥鏃堕棿锛堝垎閽燂級锛岄粯璁わ細120 + * @return + * @date 2023-03-28 + */ + public long getTokenExpireWeb() { + return tokenExpireWeb; + } + + public void setTokenExpireWeb(long tokenExpireWeb) { + this.tokenExpireWeb = tokenExpireWeb; + } + + /** + * 杩斿洖绉诲姩绔痶oken澶辨晥鏃堕棿锛堝垎閽燂級锛岄粯璁わ細60 * 24 * 15 锛�15澶╋級 + * @return + * @date 2023-03-28 + */ + public long getTokenExpireMobile() { + return tokenExpireMobile; + } + + public void setTokenExpireMobile(long tokenExpireMobile) { + this.tokenExpireMobile = tokenExpireMobile; + } + + public boolean isAllowPcUserAccessApp() { + return allowPcUserAccessApp; + } + + /** + * 璁剧疆鏄惁鍏佽'鍚庡彴PC鐢ㄦ埛'璁块棶鐧诲綍鎵嬫満APP + * @param allowPcUserAccessApp + * @date 2023-03-20 + */ + public void setAllowPcUserAccessApp(boolean allowPcUserAccessApp) { + this.allowPcUserAccessApp = allowPcUserAccessApp; + } + + /** + * 鏄惁鍚敤璺ㄥ煙閰嶇疆锛屽湪 Gateway 妯″紡涓嬶紝鐢变簬缃戝叧宸茬粡閰嶇疆锛岃繖閲屼笟鍔″氨涓嶉渶瑕侀噸澶嶉厤缃簡銆� + * @return + * @date 2022-12-28 + */ + public boolean isCorsEnabled() { + return corsEnabled; + } + + public void setCorsEnabled(boolean corsEnabled) { + this.corsEnabled = corsEnabled; + } + + /** + * 鑾峰彇瓒呯骇绠$悊鍛樺瘑鐮�(绉樻枃) + * @return + * @date 2022-12-02 + */ + public String getSupervisorPassword() { + return supervisorPassword; + } + + public void setSupervisorPassword(String supervisorPassword) { + this.supervisorPassword = supervisorPassword; + } + + /** + * 鑾峰緱閰嶇疆鐨勫凡璁よ瘉鐢ㄦ埛閮借兘璁块棶鐨勫湴鍧�闆嗗悎銆� + * @return + * @date 2022-11-13 + */ + public List<String> getPermitList() { + return permitList; + } + + public void setPermitList(List<String> permitList) { + this.permitList = permitList; + } + + /** + * 鑾峰緱閰嶇疆鐨勫尶鍚嶈闂湴鍧�闆嗗悎 + * @return + */ + public List<String> getAnonymousList() { + return anonymousList; + } + + public void setAnonymousList(List<String> anonymousList) { + this.anonymousList = anonymousList; + } + + /** + * 鐢ㄦ埛鍚嶅瘑鐮佹柟寮忕櫥褰曪紝閰嶇疆鐨勯獙璇佺爜鎻愪緵鑰呫�� + * @return + * @date 2023-03-14 + */ + public String getLoginCaptchaUserPass() { + return loginCaptchaUserPass; + } + + public void setLoginCaptchaUserPass(String loginCaptchaUserPass) { + this.loginCaptchaUserPass = loginCaptchaUserPass; + } + + /** + * 鎵嬫満鐭俊鐧诲綍鏂瑰紡锛岄厤缃殑楠岃瘉鐮佹彁渚涜�呫�� + * @return + * @date 2023-03-14 + */ + public String getLoginCaptchaSmsCode() { + return loginCaptchaSmsCode; + } + + public void setLoginCaptchaSmsCode(String loginCaptchaSmsCode) { + this.loginCaptchaSmsCode = loginCaptchaSmsCode; + } + + private String loginCaptchaUserPass = null; + private String loginCaptchaSmsCode = null; +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/config/WebSecurityConfig.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/config/WebSecurityConfig.java new file mode 100644 index 0000000..90761ab --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/config/WebSecurityConfig.java @@ -0,0 +1,492 @@ +package com.iplatform.security.config; + +import com.iplatform.base.UserCacheProvider; +import com.iplatform.base.UserLoginCache; +import com.iplatform.base.cache.MenuCacheProvider; +import com.iplatform.base.captcha.JigsawCaptchaProvider; +import com.iplatform.base.captcha.NoneCaptchaProvider; +import com.iplatform.base.captcha.ThirdPartyCaptchaProvider; +import com.iplatform.base.service.UserServiceImpl; +import com.iplatform.base.util.UserUtils; +import com.iplatform.core.PlatformConfiguration; +import com.iplatform.model.po.S_user_core; +import com.iplatform.security.DefaultAuthenticationFailureHandler; +import com.iplatform.security.DefaultAuthenticationProvider; +import com.iplatform.security.DefaultLogoutSuccessHandler; +import com.iplatform.security.DefaultResourceLoaderProvider; +import com.iplatform.security.DefaultUserDetailsService; +import com.iplatform.security.FailedAuthenticationEntryPoint; +import com.iplatform.security.JwtAuthenticationTokenFilter; +import com.iplatform.security.callback.EncryptPasswordLoginCallback; +import com.iplatform.security.callback.MobilePassCaptchaLoginCallback; +import com.iplatform.security.callback.NoneCaptchaLoginCallback; +import com.iplatform.security.callback.SmsCodeLoginCallback; +import com.iplatform.security.callback.ThirdPartyLoginCallback; +import com.iplatform.security.callback.WechatLoginCallback; +import com.iplatform.security.event.RoleSecurityUpdateListener; +import com.iplatform.security.util.SecurityConfigUtils; +import com.walker.cache.CacheProvider; +import com.walker.infrastructure.utils.StringUtils; +import com.walker.web.CaptchaProvider; +import com.walker.web.CaptchaResult; +import com.walker.web.TokenGenerator; +import com.walker.web.UserOnlineProvider; +import com.walker.web.UserPrincipal; +import com.walker.web.security.DefaultAccessDecisionManager; +import com.walker.web.security.DefaultAccessDeniedHandler; +import com.walker.web.security.DefaultSecurityMetadataSource; +import com.walker.web.security.ResourceLoadProvider; +import com.walker.web.token.JwtTokenGenerator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutFilter; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +import java.util.List; + +@Configuration +public class WebSecurityConfig extends PlatformConfiguration { + + private MenuCacheProvider menuCacheProvider; + + private UserServiceImpl userService; + + private UserOnlineProvider userOnlineProvider; + private UserCacheProvider userCacheProvider; + private UserLoginCache userLoginCache; + + @Autowired + public WebSecurityConfig(MenuCacheProvider menuCacheProvider + , UserServiceImpl userService, UserOnlineProvider userOnlineProvider, UserCacheProvider userCacheProvider + , UserLoginCache userLoginCache){ + this.menuCacheProvider = menuCacheProvider; + this.userService = userService; + this.userOnlineProvider = userOnlineProvider; + this.userCacheProvider = userCacheProvider; + // 2023-07-11 + this.userLoginCache = userLoginCache; + } + + @Bean + public SecurityProperties securityProperties(){ + return new SecurityProperties(); + } + + /** + * HttpSecurity锛氬拷鐣� antMatchers 涓娇鐢ㄧ殑绔偣鐨勮韩浠介獙璇侊紝鍏朵粬瀹夊叏鍔熻兘灏嗙敓鏁堛��<br></br> + * WebSecurity锛氱洿鎺ュ拷鐣ヤ篃涓嶄細杩涜 CSRF xss绛夋敾鍑讳繚鎶ゃ�� + * @param http + * @return + * @throws Exception + */ + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + + DefaultUserDetailsService userDetailsService = userDetailsService(this.securityProperties(), this.userCacheProvider); + http.userDetailsService(userDetailsService); + // CSRF绂佺敤锛屽洜涓轰笉浣跨敤session + http.csrf().disable(); + // ??? + http.headers().frameOptions().disable(); + + // 鐧诲綍琛屼负鐢辫嚜宸卞疄鐜帮紝鍙傝�� AuthController#login + http.formLogin().disable().httpBasic().disable(); + + // 鍖垮悕璧勬簮璁块棶鏉冮檺锛岃繑鍥炴棤鏉冮檺鎻愮ず鎺ュ彛 + http.exceptionHandling().authenticationEntryPoint(failedAuthenticationEntryPoint()) + // 宸茶璇佺敤鎴锋棤鏉冮檺璁块棶閰嶇疆 + .accessDeniedHandler(this.accessDeniedHandler()) + .and() + // 鍩轰簬token锛屾墍浠ヤ笉闇�瑕乻ession + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + +// http.formLogin().loginProcessingUrl("/login") +// .failureHandler(this.authenticationFailureHandler()); + // 娉ㄦ剰锛氳繖閲屼笉鑳介厤缃笂闈㈢殑鐧诲綍锛屽惁鍒欏氨涓嶄細鎵ц鑷繁瀹炵幇鐨�/login鏂规硶銆�2022-11-11 + http.logout().logoutUrl("/logout").logoutSuccessHandler(this.logoutSuccessHandler()).permitAll(); + + // 鍖垮悕璁块棶闆嗗悎锛�2022-11-07 + List<String> anonymousList = this.securityProperties().getAnonymousList(); + if(!StringUtils.isEmptyList(anonymousList)){ + http.authorizeHttpRequests().antMatchers(anonymousList.toArray(new String[]{})).permitAll(); + } +// http.authorizeHttpRequests().antMatchers("/login", "/register", "/captchaImage", "/test/**").permitAll(); +// http.authorizeHttpRequests().antMatchers("/static/**", "/test/**").permitAll(); +// http.authorizeHttpRequests().antMatchers("/security/**").hasAuthority("query_user"); + + // 2023-03-21 娉ㄩ噴鎺夛紝璋冭瘯activiti7鏃跺彂鐜板拰涓嬮潰閲嶅锛� + // http.addFilterBefore(securityInterceptor(), FilterSecurityInterceptor.class); + /*http.authorizeHttpRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>(){ + @Override + public <O extends FilterSecurityInterceptor> O postProcess(O object) { + object.setAccessDecisionManager(accessDecisionManager());//鍐崇瓥绠$悊鍣� + object.setSecurityMetadataSource(securityMetadataSource());//瀹夊叏鍏冩暟鎹簮 + return object; + } + });*/ + + // 2023-01-28 閰嶇疆鑷畾涔夎璇佹彁渚涜��(瀵嗙爜楠岃瘉鐢�) + http.authenticationProvider(this.authenticationProvider(userDetailsService, securityProperties())); + + // 鎵�鏈夎姹傞兘闇�瑕佽璇� + http.authorizeHttpRequests().anyRequest().authenticated(); + // 浣跨敤鑷畾涔夊姩鎬佹嫤鎴櫒锛屾嫤鎴墍鏈夋潈闄愯姹傦紝2022-11-02 + http.addFilterBefore(securityInterceptor(), FilterSecurityInterceptor.class); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // token鎷︽埅杩囨护鍣紝2022-11-02 + // 蹇呴』鍦ㄨ繖閲屾坊鍔犳嫤鎴紝涓嶈兘鏀惧湪'FilterSecurityInterceptor'涔嬪悗锛屽洜涓哄鏋滄斁鍦ㄤ箣鍚庯紝閭d箞灏辨棤娉曡幏寰楃敤鎴蜂俊鎭紝浠庤�屾棤娉� + // 鑾峰緱鐢ㄦ埛鎵�鍏锋湁鐨勬潈闄愯鑹查泦鍚�:roleIdList銆�2022-11-14(2) + http.addFilterBefore(jwtAuthenticationTokenFilter(userDetailsService), UsernamePasswordAuthenticationFilter.class); +// http.addFilterBefore(jwtAuthenticationTokenFilter(), DefaultAuthenticationFilter.class); + // 灏濊瘯璁﹋wt鍦║RL鏉冮檺涔嬪悗鎵嶆嫤鎴�, 2022-11-14(1) + // 娉ㄦ剰锛氫互涓� UsernamePasswordAuthenticationFilter 闇�瑕佸幓鎺夋墠鑳界敓鏁� +// http.addFilterAfter(jwtAuthenticationTokenFilter(), FilterSecurityInterceptor.class); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if(this.securityProperties().isCorsEnabled()){ + // 瑙e喅璺ㄥ煙杩囨护鍣紝2022-11-06 + http.addFilterBefore(this.corsFilter().getFilter(), JwtAuthenticationTokenFilter.class); + // 鏈煡锛�2022-11-11 + http.addFilterBefore(this.corsFilter().getFilter(), LogoutFilter.class); + } else { + System.out.println("涓嶆坊鍔犺法鍩熻繃婊ゅ櫒: "); + } + + return http.build(); + } + + /** + * 鑾峰彇AuthenticationManager锛堣璇佺鐞嗗櫒锛夛紝鐧诲綍鏃惰璇佷娇鐢� + * @param authenticationConfiguration + * @return + * @throws Exception + */ + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + + @Bean + public DefaultUserDetailsService userDetailsService(SecurityProperties securityProperties, UserCacheProvider userCacheProvider){ + DefaultUserDetailsService userDetailsService = new DefaultUserDetailsService(); + userDetailsService.setUserService(this.userService); +// userDetailsService.setPasswordEncoder(passwordEncoder()); + userDetailsService.setSecurityProperties(securityProperties); + userDetailsService.setMenuCacheProvider(this.menuCacheProvider); + System.out.println("create UserDetailsService = " + userDetailsService); + + // 2023-05-07锛岃繖閲屾妸瓒呯骇绠$悊鍛樺垵濮嬪寲鍒扮紦瀛� + UserPrincipal<S_user_core> userPrincipal = UserUtils.createSupervisor(securityProperties.getSupervisorPassword()); + userCacheProvider.putUser(userPrincipal.getUserInfo()); + return userDetailsService; + } + + @Bean + public PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); + } + + /** + * 鍖垮悕鐢ㄦ埛鏃犳硶璁块棶寮傚父杩斿洖 + * @return + */ + @Bean + public AuthenticationEntryPoint failedAuthenticationEntryPoint(){ + return new FailedAuthenticationEntryPoint(); + } + + /** + * 宸茶璇佺敤鎴锋嫆缁濊闂祫婧愩�� + * @return + */ + @Bean + public AccessDeniedHandler accessDeniedHandler(){ + return new DefaultAccessDeniedHandler(); + } + + @Bean + public AuthenticationFailureHandler authenticationFailureHandler(){ + return new DefaultAuthenticationFailureHandler(); + } + + @Bean + public LogoutSuccessHandler logoutSuccessHandler(){ + DefaultLogoutSuccessHandler logoutSuccessHandler = new DefaultLogoutSuccessHandler(); + logoutSuccessHandler.setUserOnlineProvider(this.userOnlineProvider); + logoutSuccessHandler.setTokenGenerator(this.tokenGenerator()); + logoutSuccessHandler.setUserLoginCache(this.userLoginCache); + return logoutSuccessHandler; + } + + @Bean + public AccessDecisionManager accessDecisionManager(){ + return new DefaultAccessDecisionManager(); + } + + @Bean + public DefaultSecurityMetadataSource securityMetadataSource(ResourceLoadProvider resourceLoadProvider){ +// DefaultResourceLoaderProvider resourceLoaderProvider = new DefaultResourceLoaderProvider(); +// resourceLoaderProvider.setMenuCacheProvider(this.menuCacheProvider); +// resourceLoaderProvider.setPermitAccessUrls(this.securityProperties().getPermitList()); +// resourceLoaderProvider.setAnonymousUrlList(this.securityProperties().getAnonymousList()); +// resourceLoaderProvider.loadResource(); + + DefaultSecurityMetadataSource securityMetadataSource = new DefaultSecurityMetadataSource(); + securityMetadataSource.setResourceLoaderProvider(resourceLoadProvider); + return securityMetadataSource; + } + + @Bean + public FilterSecurityInterceptor securityInterceptor(){ +// DefaultSecurityInterceptor securityInterceptor = new DefaultSecurityInterceptor(); + FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); + securityInterceptor.setSecurityMetadataSource(securityMetadataSource(this.resourceLoadProvider())); + securityInterceptor.setAccessDecisionManager(accessDecisionManager()); + logger.info("鍒涘缓锛欶ilterSecurityInterceptor"); + return securityInterceptor; + } + + /** + * 瀹氫箟token杩囨护鍣� + * @return + */ + @Bean + public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(DefaultUserDetailsService userDetailsService){ + JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter = new JwtAuthenticationTokenFilter(); + jwtAuthenticationTokenFilter.setTokenGenerator(tokenGenerator()); + jwtAuthenticationTokenFilter.setUserOnlineProvider(this.userOnlineProvider); + jwtAuthenticationTokenFilter.setDefaultUserDetailsService(userDetailsService); + jwtAuthenticationTokenFilter.setSecurityProperties(this.securityProperties()); + return jwtAuthenticationTokenFilter; + } + + @Bean + public TokenGenerator tokenGenerator(){ + return new JwtTokenGenerator(); + } + + /** + * 寰俊鐧诲綍鍥炶皟瀹炵幇銆� + * @param passwordEncoder + * @param tokenGenerator + * @return + * @date 2023-07-27 + */ + @Bean + public WechatLoginCallback wechatLoginCallback(PasswordEncoder passwordEncoder, TokenGenerator tokenGenerator){ + WechatLoginCallback callback = new WechatLoginCallback(); + callback.setTokenGenerator(tokenGenerator); + callback.setPasswordEncoder(passwordEncoder); + callback.setCaptchaProvider(new NoneCaptchaProvider()); + return callback; + } + + /** + * 绗笁鏂圭殑瀵规帴鐧诲綍鍥炶皟瀹炵幇銆傦紙涓洪绠椾竴浣撳寲瀵规帴浣跨敤锛屾洿澶氶渶瑕佹娊璞★級 + * @param passwordEncoder + * @param tokenGenerator + * @return + * @date 2023-07-03 + */ + @Bean + public ThirdPartyLoginCallback thirdPartyLoginCallback(PasswordEncoder passwordEncoder, TokenGenerator tokenGenerator){ + ThirdPartyLoginCallback callback = new ThirdPartyLoginCallback(); + callback.setTokenGenerator(tokenGenerator); + callback.setPasswordEncoder(passwordEncoder); + callback.setCaptchaProvider(new ThirdPartyCaptchaProvider()); + return callback; + } + + /** + * 绉诲姩绔娇鐢細鐢ㄦ埛鍚嶃�佸瘑鐮侊紙AES锛� + 鏅�氶獙璇佺爜鐧诲綍鏂瑰紡銆� + * @param passwordEncoder + * @param tokenGenerator + * @param securityProperties + * @param smsCaptchaProvider + * @param imageCaptchaProvider + * @param jigsawCaptchaProvider + * @return + * @date 2023-12-28 + */ + @Bean + public MobilePassCaptchaLoginCallback mobilePassCaptchaLoginCallback(PasswordEncoder passwordEncoder + , TokenGenerator tokenGenerator, SecurityProperties securityProperties + , CaptchaProvider<CaptchaResult> smsCaptchaProvider + , CaptchaProvider<CaptchaResult> imageCaptchaProvider + , JigsawCaptchaProvider jigsawCaptchaProvider){ + MobilePassCaptchaLoginCallback loginCallback = new MobilePassCaptchaLoginCallback(); + loginCallback.setTokenGenerator(tokenGenerator); + loginCallback.setPasswordEncoder(passwordEncoder); + // 閰嶇疆缁勮楠岃瘉鐮佹彁渚涜�咃紝2023-12-28 + CaptchaProvider<CaptchaResult> captchaProvider = SecurityConfigUtils + .findCaptchaProvider(securityProperties.getLoginCaptchaUserPass() + , smsCaptchaProvider, imageCaptchaProvider, jigsawCaptchaProvider); + loginCallback.setCaptchaProvider(captchaProvider); + return loginCallback; + } + + /** + * 璐﹀彿銆佸瘑鐮侊紙鍔犲瘑鏂瑰紡锛夌櫥褰曠殑鍥炶皟瀹炵幇锛屼笉鍖呭惈锛氱敤鎴烽獙璇佺爜銆�<p>閫傚悎鍦ㄧЩ鍔ㄧ浣跨敤</p> + * @param passwordEncoder + * @param tokenGenerator + * @return + * @date 2023-03-20 + */ + @Bean + public NoneCaptchaLoginCallback noneCaptchaPasswordLoginCallback(PasswordEncoder passwordEncoder + , TokenGenerator tokenGenerator){ + NoneCaptchaLoginCallback encryptPasswordLoginCallback = new NoneCaptchaLoginCallback(); + encryptPasswordLoginCallback.setTokenGenerator(tokenGenerator); + encryptPasswordLoginCallback.setPasswordEncoder(passwordEncoder); + encryptPasswordLoginCallback.setCaptchaProvider(new NoneCaptchaProvider()); + return encryptPasswordLoginCallback; + } + + /** + * 鐢ㄦ埛鍚嶃�佸瘑鐮侊紙鏄庢枃锛夌櫥褰曟柟寮忓洖璋冨疄鐜帮紝鍖呭惈锛氶獙璇佺爜缁勪欢锛岄�傚悎PC绔娇鐢ㄣ�� + * @param tokenGenerator + * @param passwordEncoder + * @return + * @date 2023-01-26 + */ + @Bean + public EncryptPasswordLoginCallback captchaPasswordLoginCallback(TokenGenerator tokenGenerator + , PasswordEncoder passwordEncoder, SecurityProperties securityProperties + , CaptchaProvider<CaptchaResult> smsCaptchaProvider + , CaptchaProvider<CaptchaResult> imageCaptchaProvider + , JigsawCaptchaProvider jigsawCaptchaProvider){ +// SimplePasswordLoginCallback webLoginCallback = new SimplePasswordLoginCallback(); + EncryptPasswordLoginCallback webLoginCallback = new EncryptPasswordLoginCallback(); + webLoginCallback.setTokenGenerator(tokenGenerator); + webLoginCallback.setUserOnlineProvider(this.userOnlineProvider); + webLoginCallback.setUserService(this.userService); + webLoginCallback.setPasswordEncoder(passwordEncoder); + // 閰嶇疆缁勮楠岃瘉鐮佹彁渚涜�咃紝2023-03-14 + CaptchaProvider<CaptchaResult> captchaProvider = SecurityConfigUtils + .findCaptchaProvider(securityProperties.getLoginCaptchaUserPass() + , smsCaptchaProvider, imageCaptchaProvider, jigsawCaptchaProvider); + webLoginCallback.setCaptchaProvider(captchaProvider); + return webLoginCallback; + } + + /** + * 鐭俊楠岃瘉鐮佺櫥褰曟柟寮忓洖璋冨疄鐜般�� + * @param tokenGenerator + * @param captchaCacheProvider + * @return + * @date 2023-01-26 + */ + @Bean + public SmsCodeLoginCallback smsCodeLoginCallback(TokenGenerator tokenGenerator + , CacheProvider<String> captchaCacheProvider, SecurityProperties securityProperties + , CaptchaProvider<CaptchaResult> smsCaptchaProvider + , CaptchaProvider<CaptchaResult> imageCaptchaProvider + , JigsawCaptchaProvider jigsawCaptchaProvider){ + SmsCodeLoginCallback smsCodeLoginCallback = new SmsCodeLoginCallback(); + smsCodeLoginCallback.setTokenGenerator(tokenGenerator); + smsCodeLoginCallback.setUserOnlineProvider(this.userOnlineProvider); + smsCodeLoginCallback.setUserService(this.userService); + smsCodeLoginCallback.setCaptchaCacheProvider(captchaCacheProvider); + // 閰嶇疆缁勮楠岃瘉鐮佹彁渚涜�咃紝2023-03-14 + CaptchaProvider<CaptchaResult> captchaProvider = SecurityConfigUtils + .findCaptchaProvider(securityProperties.getLoginCaptchaSmsCode() + , smsCaptchaProvider, imageCaptchaProvider, jigsawCaptchaProvider); + smsCodeLoginCallback.setCaptchaProvider(captchaProvider); + return smsCodeLoginCallback; + } + + /** + * 瑙e喅鍚屾簮璺ㄥ煙闂 + * @return + */ + @Bean + public FilterRegistrationBean<CorsFilter> corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + if(!this.securityProperties().isCorsEnabled()){ + return new FilterRegistrationBean<>(new CorsFilter(source)); + } + + // 瀵规帴鍙i厤缃法鍩熻缃� + source.registerCorsConfiguration("/**", buildConfig()); + System.out.println("閰嶇疆璺ㄥ煙杩囨护鍣紝this.securityProperties().isCorsEnabled() = true"); + //鏈夊涓猣ilter鏃舵澶勮缃敼CorsFilter鐨勪紭鍏堟墽琛岄『搴� + FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source)); + bean.setOrder(Ordered.HIGHEST_PRECEDENCE); + return bean; + } + + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + corsConfiguration.addExposedHeader("*"); + return corsConfiguration; + } + + /** + * 閰嶇疆鑷畾涔夎璇佹彁渚涜�咃紝鑷繁瀹炵幇瀵嗙爜璁よ瘉缁嗚妭锛屽惁鍒檚pring浼氶粯璁ゅ瘑鐮佹瘮杈冿紝瀵艰嚧鎵嬫満鐭俊楠岃瘉鐮佷綔涓哄瘑鐮佹瘮杈冨け鏁堛�� + * @param userDetailsService + * @return + * @date 2023-01-28 + */ + @Bean + public DefaultAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService + , SecurityProperties securityProperties){ + DefaultAuthenticationProvider authenticationProvider = new DefaultAuthenticationProvider(); + authenticationProvider.setUserDetailsService(userDetailsService); + System.out.println("isAllowPcUserAccessApp = " + securityProperties.isAllowPcUserAccessApp()); + authenticationProvider.setAllowPcUserAccessApp(securityProperties.isAllowPcUserAccessApp()); + authenticationProvider.setHideUserNotFoundExceptions(false); // 蹇呴』璁剧疆锛屽惁鍒欎笉浼氭姏鍑鸿寮傚父锛�2023-06-28 + return authenticationProvider; + } + + /** + * 鎶婅祫婧愭彁渚涜�呯嫭绔嬪嚭鏉ワ紝鍙互澶嶇敤銆� + * @return + * @date 2023-05-07 + */ + @Bean + public ResourceLoadProvider resourceLoadProvider(){ + DefaultResourceLoaderProvider resourceLoaderProvider = new DefaultResourceLoaderProvider(); + resourceLoaderProvider.setMenuCacheProvider(this.menuCacheProvider); + resourceLoaderProvider.setPermitAccessUrls(this.securityProperties().getPermitList()); + resourceLoaderProvider.setAnonymousUrlList(this.securityProperties().getAnonymousList()); + resourceLoaderProvider.loadResource(); + return resourceLoaderProvider; + } + + /** + * 瑙掕壊鏉冮檺鍙樻洿鍚庯紝澶勭悊閫氱煡锛屽苟閲嶆柊鍔犺浇璧勬簮淇℃伅銆� + * @param resourceLoadProvider + * @return + * @date 2023-05-07 + */ + @Bean + public RoleSecurityUpdateListener roleSecurityUpdateListener(ResourceLoadProvider resourceLoadProvider){ + RoleSecurityUpdateListener listener = new RoleSecurityUpdateListener(); + listener.setResourceLoaderProvider(resourceLoadProvider); + return listener; + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/controller/SecurityController.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/controller/SecurityController.java new file mode 100644 index 0000000..2645ca5 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/controller/SecurityController.java @@ -0,0 +1,439 @@ +package com.iplatform.security.controller; + +import com.iplatform.base.SecuritySpi; +import com.iplatform.base.SystemController; +import com.iplatform.base.cache.MenuCacheProvider; +import com.iplatform.base.callback.SecurityCallback; +import com.iplatform.base.config.SecurityUserProperties; +import com.iplatform.base.config.TcpProperties; +import com.iplatform.base.exception.LoginException; +import com.iplatform.base.pojo.RequestLogin; +import com.iplatform.base.service.MenuServiceImpl; +import com.iplatform.base.util.MenuUtils; +import com.iplatform.base.util.menu.MenuTree; +import com.iplatform.base.util.menu.SystemMenu; +import com.iplatform.model.po.S_user_core; +import com.iplatform.model.vo.MenuVo; +import com.iplatform.model.vo.RouterVo; +import com.walker.infrastructure.utils.JsonUtils; +import com.walker.infrastructure.utils.StringUtils; +import com.walker.web.ResponseValue; +import com.walker.web.UserPrincipal; +import com.walker.web.UserType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@RestController +public class SecurityController extends SystemController { + +// private CacheProvider<String> captchaCacheProvider; +// private AuthenticationManager authenticationManager; +// private TokenGenerator tokenGenerator; +// private UserOnlineProvider userOnlineProvider; + private MenuServiceImpl menuService; + private MenuCacheProvider menuCacheProvider; +// private WebAgentService webAgentService; +// private LogServiceImpl logService; +// private LogProperties logProperties; +// // 2023-03-22 +// private LoginServiceImpl loginService; +// // 2023-03-28 +// private SecurityProperties securityProperties; + private TcpProperties tcpProperties; + + private SecuritySpi securitySpi; + private SecurityUserProperties securityUserProperties; + + @Autowired + public SecurityController( +// CacheProvider<String> captchaCacheProvider +// , AuthenticationManager authenticationManager, TokenGenerator tokenGenerator +// , UserOnlineProvider userOnlineProvider + MenuServiceImpl menuService, MenuCacheProvider menuCacheProvider +// , WebAgentService webAgentService, LogServiceImpl logService, LogProperties logProperties +// , LoginServiceImpl loginService +// , SecurityProperties securityProperties + , TcpProperties tcpProperties, SecuritySpi securitySpi, SecurityUserProperties securityUserProperties){ +// this.captchaCacheProvider = captchaCacheProvider; +// this.authenticationManager = authenticationManager; +// this.tokenGenerator = tokenGenerator; +// this.userOnlineProvider = userOnlineProvider; + this.menuService = menuService; + this.menuCacheProvider = menuCacheProvider; +// this.webAgentService = webAgentService; +// this.logService = logService; +// this.logProperties = logProperties; +// this.loginService = loginService; +// this.securityProperties = securityProperties; + this.tcpProperties = tcpProperties; + this.securitySpi = securitySpi; + this.securityUserProperties = securityUserProperties; + } + + @PostMapping("/login") +// public ResponseValue login(@RequestBody RequestLogin requestLogin){ + public ResponseValue login(@RequestBody String raw){ + logger.debug("login = " + raw); + RequestLogin requestLogin = null; + try { + requestLogin = JsonUtils.jsonStringToObject(raw, RequestLogin.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + String username = requestLogin.getUsername(); + String password = requestLogin.getPassword(); + + if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){ + return ResponseValue.error("璇疯緭鍏ョ敤鎴峰悕鎴栧瘑鐮�"); + } + + /*// 2023-01-26 涓轰簡鏀寔澶氱鐧诲綍鏂瑰紡锛屼娇鐢ㄧ櫥褰曞洖璋冨鐞嗗叿浣撶櫥褰曠粏鑺傘�� + PlatformLoginCallback loginCallback = LoginCallbackUtils.getLoginCallbackBean(LoginType.getType(requestLogin.getLoginType()), true); + + boolean captchaEnabled = this.getArgumentVariable(ArgumentsConstants.KEY_SECURITY_CAPTCHA_ENABLED).getBooleanValue(); + // 2023-01-26 杩欓噷APP绔槸涓嶉渶瑕侀獙璇佺爜鐨� + if(captchaEnabled){ + CaptchaProvider<CaptchaResult> captchaProvider = loginCallback.getCaptchaProvider(); + if(captchaProvider == null){ + return ResponseValue.error("绯荤粺闇�瑕侀獙璇佺爜锛屼絾鐧诲綍鏈厤缃�:" + loginCallback.getClass().getName()); + } + if(StringUtils.isEmpty(requestLogin.getVerifyType())){ + return ResponseValue.error("璇锋眰閿欒锛氶獙璇佺爜绫诲瀷涓虹┖"); + } + if(!requestLogin.getVerifyType().equals(captchaProvider.getCaptchaType().getIndex())){ + throw new IllegalArgumentException("鍓嶇閰嶇疆鐨勯獙璇佺爜绫诲瀷涓庡悗鍙颁笉涓�鑷�! verifyType = " + captchaProvider.getCaptchaType()); + } + if(loginCallback.isValidateCaptcha()){ + logger.debug("闇�瑕侀獙璇佺爜锛実etCaptchaType={}", loginCallback.getCaptchaProvider().getCaptchaType()); + String error = this.validateCaptcha(username, requestLogin.getCode(), requestLogin.getUuid(), captchaProvider); + if(error != null){ + return ResponseValue.error(error); + } + } + } + + // 鐢ㄦ埛楠岃瘉 + Authentication authentication = null; + + try{ +// UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + DefaultAuthenticationToken authenticationToken = new DefaultAuthenticationToken(username, password, requestLogin); + // 杩欓噷鏀惧叆绾跨▼锛屽悗闈serDetailsService浼氫娇鐢� + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + authentication = authenticationManager.authenticate(authenticationToken); + + } catch (Exception e){ + this.recordLoginInfo(username, String.valueOf(ResponseCode.ERROR.getCode()), "鐧诲綍鏈垚鍔熻璇�", 0, null, null); + if (e instanceof BadCredentialsException){ + return ResponseValue.error(ResponseCode.USER_CREDENTIALS_ERROR.getCode(), ResponseCode.USER_CREDENTIALS_ERROR.getMessage()); + } else { + if(e instanceof UsernameNotFoundException){ + logger.debug(".............鐢ㄦ埛涓嶅瓨鍦細" + username); + } + // 2023-03-20 + // 鐧诲綍楠岃瘉鎶涘嚭寮傚父锛屼細鍦ㄨ繖閲岀粺涓�澶勭悊锛屽锛歅cUserStopAppException銆� + // DefaultAuthenticationProvider + return ResponseValue.error(ResponseCode.USER_CREDENTIALS_ERROR.getCode(), e.getMessage()); + } + } + + DefaultUserDetails userDetails = (DefaultUserDetails)authentication.getPrincipal(); + if(this.logger.isDebugEnabled()){ + logger.debug(userDetails.getUserPrincipal().toString()); + } + + // 2023-03-20锛屽浜庣┖楠岃瘉鐮佺被鍨嬶紙鐧诲綍鏂瑰紡锛夛紝闇�瑕佸悗鍙拌嚜鍔ㄧ敓鎴恥uid锛屽洜涓哄墠绔病鏈夋満浼氳姹傞獙璇佺爜鑾峰緱uuid + if(loginCallback.getCaptchaProvider().getCaptchaType() == CaptchaType.None){ + requestLogin.setUuid(IdUtils.simpleUUID()); + } + + // 娣诲姞token澶辨晥鏃堕棿锛堜粠閰嶇疆鑾峰彇锛夛紝2023-03-28 + long expiredMinutes = SecurityConfigUtils.getTokenExpireMinutes(requestLogin.getClientType(), securityProperties); + String token = TokenUtils.generateToken(userDetails.getUserPrincipal().getId() + , userDetails.getUsername(), requestLogin.getUuid(), this.tokenGenerator, expiredMinutes); + logger.debug("token澶辨晥鍒嗛挓:{}", expiredMinutes); +// String token = this.tokenGenerator.createToken(requestLogin.getUuid(), userDetails.getUserPrincipal().getId() +// , VariableConstants.DEFAULT_TOKEN_EXPIRED_MINUTES, VariableConstants.TOKEN_SECRET); + // 缂撳瓨鐧诲綍淇℃伅 + this.userOnlineProvider.cacheUserPrincipal(requestLogin.getUuid(), userDetails.getUserPrincipal()); + // 鎶婃垚鍔熺櫥褰曟棩蹇楋紝涓巙uid鍏宠仈淇濆瓨鏀句竴璧凤紝鍦ㄥ紓姝ヤ腑璋冪敤銆�2023-03-23 + this.recordLoginInfo(username, String.valueOf(ResponseCode.SUCCESS.getCode()), "鐧诲綍鎴愬姛" + , userDetails.getUserPrincipal().getUserInfo().getId(), requestLogin.getUuid(), requestLogin.getClientType()); + + // 2023-05-12锛屽姞涓婄敤鎴蜂俊鎭紙鍟嗘埛绯荤粺鐢級 + Map<String, Object> param = new HashMap<>(2); + param.put(com.walker.web.Constants.TOKEN_NAME, token); + param.put(SecurityConstants.KEY_USER_INFO, UserUtils.acquireClientUserInfo(userDetails.getUserPrincipal().getUserInfo(), token)); +// */ + Map<String, Object> param = null; + try { + param = this.securitySpi.login(requestLogin); + return ResponseValue.success(param); + } catch (LoginException e) { + return ResponseValue.error(e.getMessage()); + } + } + + @RequestMapping("/getInfo") + public ResponseValue getUserInfo(){ + UserPrincipal<S_user_core> userPrincipal = this.getCurrentUserPrincipal(); + Map<String, Object> data = new HashMap<>(4); + + // 2023-10-13锛屽鍔犳潈闄愯嚜瀹氫箟鍔犺浇鍥炶皟锛屼负涓氬姟棰勭暀閽╁瓙 + SecurityCallback securityCallback = this.getPlatformCallback(SecurityCallback.class); + + // permissions锛� + // 璇ラ泦鍚堢敤浜庨�傞厤鑻ヤ緷鍓嶇锛屽悗缁墠绔皢涓嶉渶瑕佽嚜宸变繚鐣欐潈闄愯矾鐢憋紝缁熶竴鍚庡彴澶勭悊杩斿洖閿欒淇℃伅銆�2022-11-12 + Set<String> perms = new HashSet<String>(); + if(userPrincipal.getUserInfo().getUser_type() == UserType.TYPE_SUPER){ + perms.add("*:*:*"); + } else { + // 鑾峰緱褰撳墠鐢ㄦ埛鎵�灞炵殑瑙掕壊ID闆嗗悎 + List<String> menuIdList = this.menuService.queryRoleMenuIdList(userPrincipal.getRoleIdList()); +// perms.addAll(this.menuCacheProvider.getPermissionSet(menuIdList)); + + if(securityCallback == null){ + // 2023-06-01 澧炲姞椤剁骇鍗曚綅鍙娇鐢ㄧ殑鑿滃崟鑼冨洿銆� + int menuScope = this.getDeptCacheProvider().getDept(userPrincipal.getUserInfo().getOrg_id()).getMenu_type(); + if(menuScope == MenuUtils.MENU_SCOPE_PLATFORM){ + // 骞冲彴鑿滃崟锛岄渶瑕佹牴鎹鑹叉煡璇� + perms.addAll(this.menuCacheProvider.getPermissionSet(menuIdList, false, menuScope)); + } else { + // 鍟嗘埛锛堥《绾ф満鏋勶級鐙珛鑿滃崟锛屼笉闇�瑕佽鑹� + perms.addAll(this.menuCacheProvider.getPermissionSet(null, true, menuScope)); + } + + } else { + // 2023-10-13 + logger.debug("瀛樺湪涓氬姟鑷畾涔夋潈闄愬洖璋冿細{}", securityCallback.getClass().getName()); + Set<String> userPermission = securityCallback.loadUserPermission(userPrincipal.getUserInfo(), menuIdList); + if(userPermission != null){ + perms.addAll(userPermission); + } + } + } + logger.debug("鐢ㄦ埛 permissions = " + perms); + +// data.put("user", userPrincipal.getUserInfo()); + data.put("roles", userPrincipal.getRoleIdList()); + data.put("permissions", perms); + data.put("isPerfectInfo", true); // 鏄惁宸插畬鍠勪俊鎭紝鏆傛椂娌$敤锛屼粎閰嶅悎鍓嶇灞曠ず銆�2023-03-20 + // 2023-08-05 鏄惁寮哄埗淇敼瀵嗙爜 + if(this.securityUserProperties.isPassDefaultModify()){ + data.put("force_change_pass", userPrincipal.getUserInfo().getModify_pwd().intValue() == 1? false : true); + } else { + data.put("force_change_pass", false); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //~ 閫傞厤鐢靛晢妯″潡锛屽鍔犲叾浠栫敤鎴峰睘鎬с��2023-05-12 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + S_user_core user = userPrincipal.getUserInfo(); + data.put("id", user.getId()); + data.put("account", user.getUser_name()); + data.put("realName", user.getNick_name()); + data.put("roleNames", null); + data.put("roleIds", StringUtils.collectionToCommaDelimitedString(userPrincipal.getRoleIdList())); +// data.put("Token", null); + data.put("phone", user.getPhonenumber()); + data.put("isSms", true); + data.put("merStarLevel", 0); + + // 2023-04-17锛寃ebsocket杩炴帴淇℃伅 + if(!this.tcpProperties.isEnabled()){ + logger.warn("鏈紑鍚�'WebSocket'"); + data.put("uri", "-1"); + } else { + data.put("uri", this.tcpProperties.getWebsocketUri()); + data.put("uid", userPrincipal.getId()); + } + + if(securityCallback != null){ + securityCallback.acquireUserInfo(data, user); + } + return ResponseValue.success(data); + } + + /** + * 鑻ヤ緷鍓嶇鏂规硶锛岃幏鍙栬矾鐢辨潈闄愩�傛殏鏃跺簾寮� + * @return + */ + @Deprecated + @GetMapping("/getRouters") + public ResponseValue getRouters(){ + List<SystemMenu> menuList = this.acquireUserMenuList(); + List<RouterVo> routerList = this.menuCacheProvider.buildMenus(menuList); + return ResponseValue.success(routerList); + } + + /** + * 鏂扮晫闈㈣繑鍥炶彍鍗曟爲锛岀粍瑁呮暟鎹�� + * @return + * @date 2023-05-12 + */ + @GetMapping("/getMenus") + public ResponseValue getMenus(){ + List<SystemMenu> menuList = this.acquireUserMenuList(); +// logger.debug("acquireUserMenuList = {}", menuList); + List<MenuVo> menuVoList = new ArrayList<>(32); + if(menuList != null){ + MenuVo menuVo = null; + for(SystemMenu menu: menuList){ + if(menu.getMenu_type().equals(MenuUtils.MENU_TYPE_BUTTON)){ + // 杩欓噷娉ㄦ剰锛岃繖娆″墠绔笉瑕佸姛鑳界偣锛屽彧瑕佽彍鍗曟湰韬��2023-05-13 + continue; + } + menuVo = new MenuVo(); + menuVo.setId(Long.parseLong(menu.getMenu_id())); + menuVo.setPid(Long.parseLong(menu.getParent_id())); + menuVo.setName(menu.getMenu_name()); + menuVo.setPerms(menu.getPerms()); + menuVo.setComponent(menu.getComponent()); + menuVo.setSort(menu.getOrder_num()); + menuVo.setIcon(menu.getIcon()); + menuVo.setMenuType(menu.getMenu_type()); +// if(menu.getMenu_type().equals(MenuUtils.MENU_TYPE_FOLDER)){ +// menuVo.setMenuType(MenuUtils.MENU_TYPE_FOLDER); +// } else if(menu.getMenu_type().equals(MenuUtils.MENU_TYPE_ITEM)){ +// menuVo.setMenuType(MenuUtils.MENU_TYPE_ITEM); +// } else { +// menuVo.setMenuType(MenuUtils.MENU_TYPE_POINT); +// } + if(StringUtils.isNotEmpty(menu.getIcon_info())){ + String[] customIcons = StringUtils.commaDelimitedListToStringArray(menu.getIcon_info()); + if(customIcons.length != 2){ + throw new IllegalArgumentException("鑷畾涔夎彍鍗曞浘鏍�(鐩稿璺緞)蹇呴』閰嶇疆涓や釜锛屽苟鐢ㄨ嫳鏂囬�楀彿鍒嗛殧锛宯ame=" + menu.getMenu_name()); + } + menuVo.setIconNormal(customIcons[0]); + menuVo.setIconActive(customIcons[1]); + } + menuVoList.add(menuVo); + } + } +// logger.debug("menuVoList = {}", menuVoList); + MenuTree menuTree = new MenuTree(menuVoList); + menuVoList = menuTree.buildTree(); + return ResponseValue.success(menuVoList); + } + + private List<SystemMenu> acquireUserMenuList(){ + List<SystemMenu> menuList = null; + UserPrincipal<S_user_core> userPrincipal = this.getCurrentUserPrincipal(); + + // 2023-10-13 褰撲笟鍔¢厤缃湁鑷畾涔夎彍鍗曞姞杞藉洖璋冨璞℃椂锛岄渶瑕佹寜鐓т笟鍔¤鍒欏姞杞姐�� + SecurityCallback securityCallback = this.getPlatformCallback(SecurityCallback.class); + if(securityCallback == null){ + if(userPrincipal.getUserInfo().getUser_type() == UserType.TYPE_SUPER){ +// menuList = this.menuCacheProvider.getMenuTree(null, false, true); + menuList = this.menuCacheProvider.getMenuList(null, MenuUtils.MENU_SCOPE_PLATFORM); + } else { + // 鑾峰緱褰撳墠鐢ㄦ埛鎵�灞炵殑瑙掕壊ID闆嗗悎 +// List<String> menuIdList = this.menuService.queryRoleMenuIdList(userPrincipal.getRoleIdList()); +// menuList = this.menuCacheProvider.getMenuTree(menuIdList, false, false); + // 2023-06-01 澧炲姞椤剁骇鍗曚綅鍙娇鐢ㄧ殑鑿滃崟鑼冨洿銆� + int menuScope = this.getDeptCacheProvider().getDept(userPrincipal.getUserInfo().getOrg_id()).getMenu_type(); + if(menuScope == MenuUtils.MENU_SCOPE_PLATFORM){ + // 骞冲彴鑿滃崟锛岄渶瑕佹牴鎹鑹叉煡璇� + menuList = this.menuCacheProvider.getMenuList(userPrincipal.getRoleIdList(), menuScope); + } else { + // 鍟嗘埛锛堥《绾ф満鏋勶級鐙珛鑿滃崟锛屼笉闇�瑕佽鑹� + menuList = this.menuCacheProvider.getMenuList(null, menuScope); + } +// menuList = this.menuCacheProvider.getMenuList(userPrincipal.getRoleIdList(), menuScope); + } + } else { + // 2023-10-13 + menuList = securityCallback.loadUserMenu(userPrincipal.getUserInfo(), userPrincipal.getRoleIdList()); + if(this.logger.isDebugEnabled()){ + logger.debug("瀛樺湪涓氬姟鑷畾涔夎彍鍗曞洖璋冿細{}", menuList); + } + } + if(menuList != null){ + // 杩囨护鎺夋寜閽潈闄愶紝鍓嶇鍙渶瑕佽彍鍗曪紝鎸夐挳鏉冮檺鍦╬ermisstion涓帶鍒� + SystemMenu menu = null; + for(Iterator<SystemMenu> it = menuList.iterator(); it.hasNext();){ + menu = it.next(); + // 1.鍘绘帀鎸夐挳鑿滃崟锛屽悓鏃讹紝鍋滅敤鐨勮彍鍗曚篃瑕佸幓鎺夈��2023-05-14 + // 2.涓嶈兘灞曠ず鐨勪篃瑕佸幓鎺夛紝is_show = 0 + if(menu.getMenu_type().equals(MenuUtils.MENU_TYPE_BUTTON) + || menu.getStatus().equals(MenuUtils.MENU_STATUS_DISABLED) + || menu.getVisible().equals(MenuUtils.MENU_INVISIBLE)){ + it.remove(); + } + } + } + return menuList; + } + +// private String validateCaptcha(String username, String code, String uuid, CaptchaProvider<CaptchaResult> captchaProvider){ +// if(StringUtils.isEmpty(uuid) || StringUtils.isEmpty(code)){ +// return "璇疯緭鍏ラ獙璇佺爜"; +// } +// +// CaptchaResult captchaResult = new CaptchaResult(); +// captchaResult.setUuid(uuid); +// captchaResult.setCode(code); +// boolean success = captchaProvider.validateCaptcha(captchaResult); +// +// // 2023-04-07 璋冩暣锛屼娇鐢ㄦ彁渚涜�呭垽鏂獙璇佺爜鏄惁姝g‘銆� +// this.captchaCacheProvider.removeCacheData(Constants.CAPTCHA_CODE_PREFIX + uuid);// 鍒犻櫎缂撳瓨鐨勯獙璇佺爜 +// +// if(!success){ +// logger.error("楠岃瘉鐮佹牎楠屽け璐�: code = " + code); +// return "楠岃瘉鐮侀敊璇�"; +// } +// return null; +// } + +// private void recordLoginInfo(String loginId, String status, String message, long userId, String uuid, String clientType){ +// if(this.logProperties.isLoginEnabled()){ +// logger.debug("寮傛璁板綍鐧诲綍鏃ュ織锛屽悗缁琛ュ厖:" + status + ", " + message); +// AsyncManager.me().execute(this.acquireLoginInfoTask(loginId, status, message, userId, uuid, clientType)); +// } +// } +// +// private TimerTask acquireLoginInfoTask(String loginId, String status, String message, Long userId +// , String uuid, String clientType){ +// HttpServletRequest request = this.getRequest(); +// final WebUserAgent webUserAgent = this.webAgentService.getWebUserAgent(request.getHeader("User-Agent"), request); +// +// return new TimerTask() { +// @Override +// public void run() { +// S_login_info login_info = new S_login_info(); +// login_info.setLogin_time(Long.parseLong(DateUtils.getDateTimeSecondForShow())); +// login_info.setUser_name(loginId); +// login_info.setMsg(message); +// login_info.setStatus(status); +// login_info.setInfo_id(NumberGenerator.getLongSequenceNumber()); +// if(webUserAgent != null){ +// login_info.setLogin_location(webUserAgent.getLocation()); +// login_info.setBrowser(webUserAgent.getBrowserName()); +// login_info.setIpaddr(webUserAgent.getIp()); +// login_info.setOs(webUserAgent.getOsName()); +// } +// +// // 2023-03-23 +// if(status.equals(String.valueOf(ResponseCode.SUCCESS.getCode()))){ +// // 鐧诲綍鎴愬姛鎵嶈褰晆uid鍏宠仈缂撳瓨 +// loginService.execUpdateUserLogin(userId, loginId, uuid, clientType, login_info); +// } else { +// // 鐧诲綍澶辫触锛屼粎璁板綍鐧诲綍鏃ュ織 +// logService.execInsertLoginLog(login_info, userId); +// } +// } +// }; +// } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/event/RoleSecurityUpdateListener.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/event/RoleSecurityUpdateListener.java new file mode 100644 index 0000000..9360832 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/event/RoleSecurityUpdateListener.java @@ -0,0 +1,40 @@ +package com.iplatform.security.event; + +import com.iplatform.base.event.RoleSecurityChangeEvent; +import com.walker.web.security.ResourceLoadProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; + +/** + * 瑙掕壊瀵瑰簲鏉冮檺鏇存柊鐩戝惉鍣紝鍦ㄨ鑹叉潈闄愪慨鏀瑰悗锛屼細瑙﹀彂璇ヤ簨浠舵潵鍝嶅簲銆� + * <p>濡傛灉涓嶉�氱煡閲嶆柊鍔犺浇锛屽垯瑙掕壊鍒嗚繃鏉冮檺鍚庯紝鐢ㄦ埛浠嶇劧鐪嬩笉鍒帮紙闇�瑕侀噸鏂板惎鍔級</p> + * @author shikeying + * @date 2023-05-07 绉绘鑰佷唬鐮� + */ +public class RoleSecurityUpdateListener implements ApplicationListener<RoleSecurityChangeEvent> { + + private Logger logger = LoggerFactory.getLogger(getClass()); + +// private MySecurityMetadataSource securityMetaSource; +// +// public void setSecurityMetaSource(MySecurityMetadataSource securityMetaSource) { +// assert (securityMetaSource != null); +// this.securityMetaSource = securityMetaSource; +// } + + private ResourceLoadProvider resourceLoaderProvider; + + public void setResourceLoaderProvider(ResourceLoadProvider securityMetaSource) { + this.resourceLoaderProvider = securityMetaSource; + } + + @Override + public void onApplicationEvent(RoleSecurityChangeEvent event) { + resourceLoaderProvider.reloadResource(); + logger.info("*************************************************"); + logger.info("* 绯荤粺閲嶆柊鍔犺浇浜嗚鑹叉潈闄愭暟鎹�"); + logger.info("*************************************************"); + } + +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/exception/PcUserStopAppException.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/exception/PcUserStopAppException.java new file mode 100644 index 0000000..4d7dc11 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/exception/PcUserStopAppException.java @@ -0,0 +1,20 @@ +package com.iplatform.security.exception; + +import org.springframework.security.core.AuthenticationException; + +/** + * PC锛堝悗鍙扮敤鎴凤級鏃犳硶璁块棶App寮傚父瀹氫箟銆� + * @author 鏃跺厠鑻� + * @date 2023-03-20 + */ +public class PcUserStopAppException extends AuthenticationException { + + public PcUserStopAppException(Throwable cause) { + super(MESSAGE, cause); + } + public PcUserStopAppException(String msg, Throwable cause) { + super(msg, cause); + } + + public static final String MESSAGE = "闈濧pp鐢ㄦ埛鏃犳硶鐧诲綍鎵嬫満绔�!"; +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/LoginCallbackUtils.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/LoginCallbackUtils.java new file mode 100644 index 0000000..d98f9f1 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/LoginCallbackUtils.java @@ -0,0 +1,69 @@ +package com.iplatform.security.util; + +import com.iplatform.base.PlatformLoginCallback; +import com.iplatform.base.callback.PlatformCallbackPostProcessor; +import com.iplatform.security.callback.EncryptPasswordLoginCallback; +import com.iplatform.security.callback.MobilePassCaptchaLoginCallback; +import com.iplatform.security.callback.NoneCaptchaLoginCallback; +import com.iplatform.security.callback.SimplePasswordLoginCallback; +import com.iplatform.security.callback.SmsCodeLoginCallback; +import com.iplatform.security.callback.ThirdPartyLoginCallback; +import com.iplatform.security.callback.WechatLoginCallback; +import com.walker.web.CaptchaType; +import com.walker.web.LoginType; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 鐧诲綍鍥炶皟宸ュ叿绫汇�� + * @author 鏃跺厠鑻� + * @date 2023-01-26 + */ +public class LoginCallbackUtils { + + protected static final Logger logger = LoggerFactory.getLogger(LoginCallbackUtils.class); + +// public static final PlatformLoginCallback getLoginCallbackBean(UserType userType){ +// if(userType == UserType.UserEquipment){ +// throw new UnsupportedOperationException("鏆備笉鏀寔璁惧杩炴帴鐧诲綍鍥炶皟"); +// } else if(userType == UserType.UserApp){ +// return getLoginCallbackBean(LoginType.MOBILE); +// } else { +// return getLoginCallbackBean(LoginType.PC); +// } +// } + + /** + * 鏍规嵁鐧诲綍绫诲瀷锛屾煡鎵剧櫥褰曞洖璋冨畾涔夊疄鐜般�� + * @param loginType 鐧诲綍绫诲瀷锛屽弬鑰冿細{@linkplain LoginType} + * @param encryptPassword 濡傛灉瀵嗙爜鏂瑰紡锛屽瘑鐮佹槸鍚﹀姞瀵� + * @return + */ + public static final PlatformLoginCallback getLoginCallbackBean(LoginType loginType, boolean encryptPassword, CaptchaType captchaType){ + if(loginType == LoginType.UserPassword){ + if(encryptPassword){ + return PlatformCallbackPostProcessor.getCallbackMultipleBean(EncryptPasswordLoginCallback.class); + } else { + logger.error("'SimplePasswordLoginCallback'杩樻湭閰嶇疆锛屾槑鏂囧瘑鐮佺櫥褰曞凡涓嶅啀鏀寔锛佷粎鐢ㄤ簬娴嬭瘯銆�"); + return PlatformCallbackPostProcessor.getCallbackMultipleBean(SimplePasswordLoginCallback.class); + } + } else if(loginType == LoginType.SmsCode){ + return PlatformCallbackPostProcessor.getCallbackMultipleBean(SmsCodeLoginCallback.class); + } else if(loginType == LoginType.MobilePassword){ + if(captchaType == CaptchaType.None){ + return PlatformCallbackPostProcessor.getCallbackMultipleBean(NoneCaptchaLoginCallback.class); + } else { + return PlatformCallbackPostProcessor.getCallbackMultipleBean(MobilePassCaptchaLoginCallback.class); + } + +// return PlatformCallbackPostProcessor.getCallbackMultipleBean(NoneCaptchaLoginCallback.class); + } else if(loginType == LoginType.ThirdParty){ + return PlatformCallbackPostProcessor.getCallbackMultipleBean(ThirdPartyLoginCallback.class); + } else if(loginType == LoginType.Wechat){ + return PlatformCallbackPostProcessor.getCallbackMultipleBean(WechatLoginCallback.class); + } else { + throw new UnsupportedOperationException("鏆備笉鏀寔鐧诲綍绫诲瀷:" + loginType); + } + } +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/MockPrincipalUtils.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/MockPrincipalUtils.java new file mode 100644 index 0000000..cc1c880 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/MockPrincipalUtils.java @@ -0,0 +1,53 @@ +package com.iplatform.security.util; + +import com.iplatform.base.DefaultUserPrincipal; +import com.iplatform.model.po.S_user_core; +import com.walker.infrastructure.utils.DateUtils; +import com.walker.web.DataStatus; +import com.walker.web.UserPrincipal; +import com.walker.web.UserType; + +public class MockPrincipalUtils { + +// /** +// * 姝e紡浠g爜锛屽垱寤鸿秴绾х鐞嗗憳鐢ㄦ埛鐧诲綍瀵硅薄 +// * @return +// */ +// public static final UserPrincipal<S_user_core> createSupervisor(String supervisorPassword){ +// S_user_core userCore = new S_user_core(); +// userCore.setId(Constants.SUPERVISOR_ID); +//// userCore.setCreateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); +// userCore.setCreate_time(DateUtils.getDateTimeNumber(System.currentTimeMillis())); +// userCore.setStatus(DataStatus.CONST_NORMAL); +// userCore.setUser_name(Constants.SUPERVISOR_NAME_DEFAULT); +// userCore.setNick_name(Constants.SUPERVISOR_NAME_ZH); +//// userCore.setPassword("123456"); // 杩欓噷瑕佷慨鏀癸紝搴旇瀛樺偍鍔犲瘑杩囧悗鐨勫瘑鐮佷俊鎭� +// userCore.setPassword(supervisorPassword); +// userCore.setUser_type(UserType.TYPE_SUPER); +// +// DefaultUserPrincipal userPrincipal = new DefaultUserPrincipal(userCore); +// return userPrincipal; +// } + + /** + * 妯℃嫙涓�涓櫘閫氱敤鎴� + * @param id 鐢ㄦ埛ID(浠ュ強鐧诲綍ID) + * @return + */ + @Deprecated + public static final UserPrincipal<S_user_core> createNormalUser(String id){ + S_user_core userCore = new S_user_core(); + userCore.setId(Long.parseLong(id)); +// userCore.setCreateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); + userCore.setCreate_time(DateUtils.getDateTimeNumber(System.currentTimeMillis())); + userCore.setStatus(DataStatus.CONST_NORMAL); + userCore.setUser_name(id); + userCore.setNick_name("婕旂ず鐢ㄦ埛"); + userCore.setPassword("123456"); // 杩欓噷瑕佷慨鏀癸紝搴旇瀛樺偍鍔犲瘑杩囧悗鐨勫瘑鐮佷俊鎭� + userCore.setUser_type(UserType.TYPE_NORMAL); + + DefaultUserPrincipal userPrincipal = new DefaultUserPrincipal(userCore); + return userPrincipal; + } + +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/ResourceLoaderUtils.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/ResourceLoaderUtils.java new file mode 100644 index 0000000..f4a8dbf --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/ResourceLoaderUtils.java @@ -0,0 +1,5 @@ +package com.iplatform.security.util; + +public class ResourceLoaderUtils { + +} diff --git a/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/SecurityConfigUtils.java b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/SecurityConfigUtils.java new file mode 100644 index 0000000..f2ecff6 --- /dev/null +++ b/iplatform-base-security-consum/src/main/java/com/iplatform/security/util/SecurityConfigUtils.java @@ -0,0 +1,58 @@ +package com.iplatform.security.util; + +import com.iplatform.base.captcha.JigsawCaptchaProvider; +import com.iplatform.base.captcha.NoneCaptchaProvider; +import com.iplatform.security.config.SecurityProperties; +import com.walker.web.CaptchaProvider; +import com.walker.web.CaptchaResult; +import com.walker.web.CaptchaType; +import com.walker.web.ClientType; +import com.walker.web.captcha.SlideCaptchaProvider; + +public class SecurityConfigUtils { + + /** + * 鏍规嵁璁惧绫诲瀷锛岃繑鍥瀟oken澶辨晥鏃堕棿锛堝垎閽燂級 + * @param clientType + * @param securityProperties + * @return + * @date 2023-03-28 + */ + public static final long getTokenExpireMinutes(String clientType, SecurityProperties securityProperties){ + if(clientType.equals(ClientType.INDEX_PC)){ + return securityProperties.getTokenExpireWeb(); + } else { + return securityProperties.getTokenExpireMobile(); + } + } + + /** + * 鏍规嵁'鐧诲綍鍥炶皟鏂瑰紡'鏌ユ壘闇�瑕佽閰嶇殑'楠岃瘉鐮佺被鍨�'銆� + * @param loginCaptchaUserPass + * @param smsCaptchaProvider + * @param imageCaptchaProvider + * @return + * @date 2023-03-14 + */ + public static final CaptchaProvider<CaptchaResult> findCaptchaProvider(String loginCaptchaUserPass + , CaptchaProvider<CaptchaResult> smsCaptchaProvider + , CaptchaProvider<CaptchaResult> imageCaptchaProvider + , JigsawCaptchaProvider jigsawCaptchaProvider){ + CaptchaProvider<CaptchaResult> captchaProvider = null; + CaptchaType captchaType = CaptchaType.getType(loginCaptchaUserPass); + if(captchaType == CaptchaType.InputCode){ + captchaProvider = imageCaptchaProvider; + } else if(captchaType == CaptchaType.SmsCode){ + captchaProvider = smsCaptchaProvider; + } else if(captchaType == CaptchaType.Slide){ + captchaProvider = new SlideCaptchaProvider(); + } else if(captchaType == CaptchaType.Jigsaw){ + captchaProvider = jigsawCaptchaProvider; + } else if(captchaType == CaptchaType.None){ + captchaProvider = new NoneCaptchaProvider(); + } else { + throw new UnsupportedOperationException("涓嶆敮鎸佺殑CaptchaType:" + loginCaptchaUserPass); + } + return captchaProvider; + } +} diff --git a/iplatform-base-security-consum/src/test/java/com/iplatform/security/TestSecurity.java b/iplatform-base-security-consum/src/test/java/com/iplatform/security/TestSecurity.java new file mode 100644 index 0000000..a6cf075 --- /dev/null +++ b/iplatform-base-security-consum/src/test/java/com/iplatform/security/TestSecurity.java @@ -0,0 +1,37 @@ +package com.iplatform.security; + +import com.iplatform.base.util.PlatformRSAUtils; +import com.walker.infrastructure.utils.Base64; +import com.walker.infrastructure.utils.Base64Utils; +import com.walker.infrastructure.utils.RSAUtil; +import org.junit.Test; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; + +public class TestSecurity { + +// @Test + public void testDecryptPassword() throws Exception{ + String encodePass = "DOEUaXiOa0y8Kq0De+P4OL/bdydlEFC+330I2lmXbz8VwHJYugLV/IPeXp31fZ5yOQvelMLwDutNtgQaRVS9L8n5ctjpYQZC3HAVDZ+6sXhE3TIH14Q8S3RhD3kE8iBVKrWd7423iCjflNwUPedFcQ0zVpJt3pC3wvDUayXIJnI="; +// String decode = Base64.decodeBase64(encode.getBytes(StandardCharsets.UTF_8)); + + byte[] keyBytes = Base64Utils.decode(PlatformRSAUtils.PRIK); + PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); + + String password = RSAUtil.decrypt(privateK, Base64.decode(encodePass.getBytes())); + System.out.println(password); + } + +// @Test + public void testGeneratePassword(){ + String raw = "123456"; + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + String encrypt = passwordEncoder.encode(raw); + System.out.println("encrypt = " + encrypt); + } +} diff --git a/pom.xml b/pom.xml index fe3cc59..7e7008d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,7 @@ <module>deploy-jar-single</module> <module>consum-base</module> <module>consum-model-pojo</module> + <module>iplatform-base-security-consum</module> </modules> <parent> @@ -44,6 +45,12 @@ <version>${consum-model-pojo.version}</version> </dependency> + <dependency> + <groupId>com.iplatform</groupId> + <artifactId>iplatform-base-security-consum</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + </dependencies> </dependencyManagement> -- Gitblit v1.9.1