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