From a4bc7ba7a708cf2867f3027f593ef72c0d8acf78 Mon Sep 17 00:00:00 2001 From: liusheng <337615773@qq.com> Date: 星期六, 06 九月 2025 17:46:14 +0800 Subject: [PATCH] 单点登陆白名单访问功能 --- ruoyi-admin/src/main/java/com/ruoyi/web/controller/hanler/IpWhitelistInterceptor.java | 82 +++++++++++++++++++++++++++ ruoyi-admin/src/main/java/com/ruoyi/web/core/config/WebConfig.java | 22 +++++++ ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java | 41 +++++++------ ruoyi-common/src/main/java/com/ruoyi/common/annotation/IpWhitelist.java | 10 +++ ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java | 5 + ruoyi-common/pom.xml | 5 + 6 files changed, 144 insertions(+), 21 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/hanler/IpWhitelistInterceptor.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/hanler/IpWhitelistInterceptor.java new file mode 100644 index 0000000..277238a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/hanler/IpWhitelistInterceptor.java @@ -0,0 +1,82 @@ +package com.ruoyi.web.controller.hanler; + +import com.ruoyi.common.annotation.IpWhitelist; +import com.ruoyi.system.domain.SysConfig; +import com.ruoyi.system.mapper.SysConfigMapper; +import org.apache.commons.net.util.SubnetUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Component +public class IpWhitelistInterceptor implements HandlerInterceptor { + @Autowired + private SysConfigMapper sysConfigMapper; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + System.out.println("澶勭悊鍣ㄧ被: " + handler.getClass().getName()); + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + if (handlerMethod.hasMethodAnnotation(IpWhitelist.class)) { + //鑾峰彇璇锋眰鐨処P锛屽垽鏂槸涓嶆槸鍦ㄧ櫧鍚嶅崟涓� + String clientIp = getClientIp(request); + if (!isIpInWhitelist(clientIp)) { + response.setStatus(HttpStatus.FORBIDDEN.value()); + response.getWriter().write("Access denied: IP address not whitelisted"); + return false; + } + } + } + return true; + } + + private String getClientIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } + + private boolean isIpInWhitelist(String ip) { + try { + SysConfig config = new SysConfig(); + config.setConfigKey("sys.ip.whitelist"); + SysConfig sysConfig = sysConfigMapper.selectConfig(config); + List<String> whitelistIps = Arrays.asList(sysConfig.getConfigValue().split(",")); + for (String whitelist : whitelistIps) { + if (whitelist.contains("/")) { + // CIDR鏍煎紡 + SubnetUtils subnetUtils = new SubnetUtils(whitelist); + if (subnetUtils.getInfo().isInRange(ip)) { + return true; + } + } else { + // 鍗曚釜IP + if (whitelist.equals(ip)) { + return true; + } + } + } + } catch (Exception e) { + return false; + } + return false; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index a5e2dd6..0ebc693 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -1,11 +1,12 @@ package com.ruoyi.web.controller.system; -import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.annotation.IpWhitelist; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginBody; +import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.RSAPublicKeyExample; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; @@ -16,11 +17,15 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.view.RedirectView; -import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; +import java.net.URI; import java.util.List; import java.util.Set; @@ -67,35 +72,33 @@ } /** - * 鍗曠偣鐧诲綍鏂规硶 + * 鍗曠偣鐧诲綍鏂规硶(闇�瑕侀厤缃甀P鐧藉悕鍗�) + * 闇�瑕佸湪sys_config琛ㄧ殑sys.ip.whitelis涓紝鍔犲叆IP鎵嶈兘璁块棶璇ユ柟娉� * - * @param loginBody 鍗曠偣鐧诲綍淇℃伅 * @return 缁撴灉 */ - @PostMapping("/SSOLogin") - public AjaxResult SSOLogin(@RequestBody LoginBody loginBody) { - AjaxResult ajax = AjaxResult.success(); + @IpWhitelist + @GetMapping("/SSOLogin") + public RedirectView SSOLogin(@RequestParam String userName, @RequestParam String orgid, @RequestParam(required = false) String deptId) { + RedirectView redirectView = new RedirectView(); // 鐢熸垚浠ょ墝 - if (StringUtils.isEmpty(loginBody.getUsername()) || StringUtils.isEmpty(loginBody.getOrgid())) { - return AjaxResult.error("鐢ㄦ埛鍚嶆垨缁勭粐鏈烘瀯鎴栭儴闂ㄤ笉鑳戒负绌�"); + if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(orgid)) { + throw new BaseException("鐢ㄦ埛鍚嶆垨缁勭粐鏈烘瀯鎴栭儴闂ㄤ笉鑳戒负绌�"); } - - if (StringUtils.isEmpty(loginBody.getDeptId())) { - loginBody.setDeptId(null); - } - String userName = loginBody.getUsername(); if (isEncryp == 1) { RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample(); - userName = rsaPublicKeyExample.decryptedData(loginBody.getUsername(), pri_key); + userName = rsaPublicKeyExample.decryptedData(userName, pri_key); } - String token = loginService.loginByUserName(userName + "&" + loginBody.getOrgid() + "&" + loginBody.getDeptId()); + String token = loginService.loginByUserName(userName + "&" + orgid + "&" + deptId); if (StringUtils.isEmpty(token)) { - return AjaxResult.error("鐧婚檰澶辫触"); + throw new BaseException("鐧婚檰澶辫触"); } - ajax.put(Constants.TOKEN, token); - return ajax; + redirectView.setUrl("http://127.0.0.1:8091/loginSSO?token=" + token + "&orgid=" + orgid + "&orgname=''" + "&ZuHuID=''&deptCode=''&redirect=''"); + redirectView.setStatusCode(HttpStatus.MOVED_PERMANENTLY); + return redirectView; } + @GetMapping("/getToken") public void getToken(HttpServletResponse response) throws IOException { // 鐢熸垚鎴栬幏鍙杢oken diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/WebConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/WebConfig.java new file mode 100644 index 0000000..ed2c101 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/WebConfig.java @@ -0,0 +1,22 @@ +package com.ruoyi.web.core.config; + +import com.ruoyi.web.controller.hanler.IpWhitelistInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private IpWhitelistInterceptor methodIpWhitelistInterceptor; + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(methodIpWhitelistInterceptor) + .addPathPatterns("/**"); + } + +} diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index a663e7e..f1bbbb7 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -211,6 +211,11 @@ <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> + <dependency> + <groupId>commons-net</groupId> + <artifactId>commons-net</artifactId> + <version>3.8.0</version> + </dependency> </dependencies> diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/IpWhitelist.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/IpWhitelist.java new file mode 100644 index 0000000..5aad150 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/IpWhitelist.java @@ -0,0 +1,10 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.*; + +@Inherited +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface IpWhitelist { +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index 921dff6..ea1a17b 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -108,9 +108,10 @@ // 杩囨护璇锋眰 .authorizeRequests() // 瀵逛簬鐧诲綍login 娉ㄥ唽register 楠岃瘉鐮乧aptchaImage 鍏佽鍖垮悕璁块棶 - .antMatchers("/login", "/register", "/captchaImage", "/qrcode/generateStaticHtml", "/qrcode/getQRcode", "/qrcode/getFormDate", "/chat", "/system/file/admin/uploadFile", "/smartor/dingtalk/sendNotification", "/patient/read/patientInfo", "/socket", "/API_ESB_Service", "/API_ESB_Service/Run", "/magic/web/**", "/smartor/serviceSubtask/phoneCallBack", "/smartor/serviceSubtask/taskPull", "/smartor/serviceSubtask/phoneCallBackYQ", "/smartor/robot/callstatus", "/smartor/robot/aidialog", "/smartor/robot/cdrinfo", "/getToken", "/smartor/subtaskAnswer/getQuestionCache", "/smartor/subtaskAnswer/saveQuestionCache", "/smartor/servicetask/getScriptInfoByCondition", "/smartor/subtaskAnswer/saveQuestionAnswer", "/smartor/import/download", "/smartor/serviceSubtask/recordAccept", "/smartor/outPath/getInfoByParam", "/smartor/serviceExternal/addDeptInfo", "/smartor/serviceExternal/**", "/sso/**","/smartor/sltdHealthcareRecord/**").permitAll() + .antMatchers("/login", "/register", "/captchaImage", "/qrcode/generateStaticHtml", "/qrcode/getQRcode", "/qrcode/getFormDate", "/chat", "/system/file/admin/uploadFile", "/smartor/dingtalk/sendNotification", "/patient/read/patientInfo", "/socket", "/API_ESB_Service", "/API_ESB_Service/Run", "/magic/web/**", "/smartor/serviceSubtask/phoneCallBack", "/smartor/serviceSubtask/taskPull", "/smartor/serviceSubtask/phoneCallBackYQ", "/smartor/robot/callstatus", "/smartor/robot/aidialog", "/smartor/robot/cdrinfo", "/getToken", "/smartor/subtaskAnswer/getQuestionCache", "/smartor/subtaskAnswer/saveQuestionCache", "/smartor/servicetask/getScriptInfoByCondition", "/smartor/subtaskAnswer/saveQuestionAnswer", "/smartor/import/download", "/smartor/serviceSubtask/recordAccept", "/smartor/outPath/getInfoByParam", "/smartor/serviceExternal/addDeptInfo", "/smartor/serviceExternal/**", "/sso/**","/smartor/sltdHealthcareRecord/**","/smartor/servicetask/getScriptByCondition","/smartor/subtaskAnswer/saveMYDQuestionAnswer").permitAll() + .antMatchers(HttpMethod.GET, "/SSOLogin/**").permitAll() // 闈欐�佽祫婧愶紝鍙尶鍚嶈闂� - .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll().antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() + .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**","/getDept/*").permitAll().antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() .antMatchers("/smartor/organization/list").permitAll() // 闄や笂闈㈠鐨勬墍鏈夎姹傚叏閮ㄩ渶瑕侀壌鏉冭璇� .anyRequest().authenticated().and().headers().frameOptions().disable(); -- Gitblit v1.9.3