From 302cdd3b6bac6670c70c2df97748d85d9fa72f84 Mon Sep 17 00:00:00 2001 From: indsvr <2394857693@qq.com> Date: Fri, 27 Jun 2025 17:57:35 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0SSO=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/adminPage/SSOController.java | 196 ++++++++++++++++++ .../WEB-INF/view/adminPage/menu.html | 3 + .../WEB-INF/view/adminPage/sso/index.html | 161 ++++++++++++++ src/main/resources/app.yml | 4 +- src/main/resources/messages.properties | 1 + src/main/resources/messages_en_US.properties | 1 + src/main/resources/messages_zh_TW.properties | 1 + 7 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/cym/controller/adminPage/SSOController.java create mode 100644 src/main/resources/WEB-INF/view/adminPage/sso/index.html diff --git a/src/main/java/com/cym/controller/adminPage/SSOController.java b/src/main/java/com/cym/controller/adminPage/SSOController.java new file mode 100644 index 00000000..b44c02ee --- /dev/null +++ b/src/main/java/com/cym/controller/adminPage/SSOController.java @@ -0,0 +1,196 @@ +package com.cym.controller.adminPage; + +import cn.hutool.core.util.StrUtil; +import com.cym.ext.AdminExt; +import com.cym.ext.Tree; +import com.cym.model.Admin; +import com.cym.model.Group; +import com.cym.service.AdminService; +import com.cym.service.GroupService; +import com.cym.service.SettingService; +import com.cym.sqlhelper.bean.Page; +import com.cym.utils.AuthUtils; +import com.cym.utils.BaseController; +import com.cym.utils.JsonResult; +import com.cym.utils.SendMailUtils; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.client.j2se.MatrixToImageWriter; +import com.google.zxing.common.BitMatrix; +import org.noear.solon.annotation.Controller; +import org.noear.solon.annotation.Inject; +import org.noear.solon.annotation.Mapping; +import org.noear.solon.core.handle.Context; +import org.noear.solon.core.handle.ModelAndView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.*; + +@Controller +@Mapping("/adminPage/sso") +public class SSOController extends BaseController { + Logger logger = LoggerFactory.getLogger(this.getClass()); + @Inject + AdminService adminService; + @Inject + SettingService settingService; + @Inject + SendMailUtils sendCloudUtils; + @Inject + AuthUtils authUtils; + @Inject + GroupService groupService; + @Inject + RemoteController remoteController; + + @Mapping("") + public ModelAndView index(ModelAndView modelAndView) { + modelAndView.put("page", ""); + modelAndView.view("/adminPage/sso/index.html"); + return modelAndView; + } + + @Mapping("addOver") + public JsonResult addOver(String id, String name, Boolean api, Integer type, String[] parentId) { + + if (StrUtil.isEmpty(id)) { + Long count = adminService.getCountByName(name); + if (count > 0) { + return renderError(m.get("adminStr.nameRepetition")); + } + } else { + Long count = adminService.getCountByNameWithOutId(name, id); + if (count > 0) { + return renderError(m.get("adminStr.nameRepetition")); + } + } + + Admin admin = new Admin(); + admin.setId(id); + admin.setName(name); + admin.setApi(api); + admin.setType(type); + + adminService.addOver(admin, parentId); + + return renderSuccess(); + } + + @Mapping("changePassOver") + public JsonResult changePassOver(String id, String pass, Boolean auth) { + Admin admin = new Admin(); + admin.setId(id); + admin.setPass(pass); + admin.setAuth(auth); + + adminService.changePassOver(admin); + + return renderSuccess(); + } + + @Mapping("detail") + public JsonResult detail(String id) { + AdminExt adminExt = new AdminExt(); + adminExt.setAdmin(sqlHelper.findById(id, Admin.class)); + adminExt.setGroupIds(adminService.getGroupIds(adminExt.getAdmin().getId())); + adminExt.getAdmin().setPass(""); + return renderSuccess(adminExt); + } + + @Mapping("del") + public JsonResult del(String id) { + String[] ids = id.split(","); + sqlHelper.deleteByIds(ids, Admin.class); + + return renderSuccess(); + } + + + + + @Mapping("getMailSetting") + public JsonResult getMailSetting() { + Map map = new HashMap<>(); + + map.put("mail_host", settingService.get("mail_host")); + map.put("mail_port", settingService.get("mail_port")); + map.put("mail_from", settingService.get("mail_from")); + map.put("mail_user", settingService.get("mail_user")); + map.put("mail_pass", settingService.get("mail_pass")); + map.put("mail_ssl", settingService.get("mail_ssl")); + map.put("mail_interval", settingService.get("mail_interval")); + + return renderSuccess(map); + } + + @Mapping("updateMailSetting") + public JsonResult updateMailSetting(String mailType, String mail_user, String mail_host, String mail_port, String mail_from, String mail_pass, String mail_ssl, String mail_interval) { + settingService.set("mail_host", mail_host); + settingService.set("mail_port", mail_port); + settingService.set("mail_user", mail_user); + settingService.set("mail_from", mail_from); + settingService.set("mail_pass", mail_pass); + settingService.set("mail_ssl", mail_ssl); + settingService.set("mail_interval", mail_interval); + + return renderSuccess(); + } + + @Mapping("testMail") + public JsonResult testMail(String mail) { + if (StrUtil.isEmpty(mail)) { + return renderError(m.get("adminStr.emailEmpty")); + } + try { + sendCloudUtils.sendMailSmtp(mail, m.get("adminStr.emailTest"), m.get("adminStr.emailTest")); + return renderSuccess(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + return renderError(m.get("commonStr.error") + ": " + e.getMessage()); + } + } + + @Mapping("testAuth") + public JsonResult testAuth(String key, String code) { + + Boolean rs = authUtils.testKey(key, code); + return renderSuccess(rs); + } + + @Mapping(value = "qr") + public void getqcode(String url, Integer w, Integer h) throws IOException { + if (StrUtil.isNotBlank(url)) { + + if (w == null) { + w = 300; + } + if (h == null) { + h = 300; + } + try { + Hashtable hints = new Hashtable(); + hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); + hints.put(EncodeHintType.MARGIN, 0); + + BitMatrix matrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, w, h, hints); + MatrixToImageWriter.writeToStream(matrix, "png", Context.current().outputStream()); + } catch (WriterException e) { + logger.error(e.getMessage(), e); + } + } + } + + @Mapping("getGroupTree") + public JsonResult getGroupTree() { + + List groups = groupService.getListByParent(null); + List treeList = new ArrayList<>(); + remoteController.fillTree(groups, treeList); + + return renderSuccess(treeList); + } +} diff --git a/src/main/resources/WEB-INF/view/adminPage/menu.html b/src/main/resources/WEB-INF/view/adminPage/menu.html index 59c7c52f..751508c8 100644 --- a/src/main/resources/WEB-INF/view/adminPage/menu.html +++ b/src/main/resources/WEB-INF/view/adminPage/menu.html @@ -77,6 +77,9 @@
${menuStr.admin}
+
+ SSO +
${menuStr.doc} diff --git a/src/main/resources/WEB-INF/view/adminPage/sso/index.html b/src/main/resources/WEB-INF/view/adminPage/sso/index.html new file mode 100644 index 00000000..7b92ed91 --- /dev/null +++ b/src/main/resources/WEB-INF/view/adminPage/sso/index.html @@ -0,0 +1,161 @@ + + + + <#include "/adminPage/common.html"/> + + + + +
+ + <#include "/adminPage/header.html"/> + <#include "/adminPage/menu.html"/> + +
+ +
+ + + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +

jsonpath表达式获取用户唯一信息,例如:$.a.b

+
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +

SSO Server会携带code访问下方地址(下方地址?code=xxxxxxx),例如:http://host/callback?code=xxxxxxx

+
+ +
+
+ + +
+ + +
+
+ +
+
+ +
+
+ + +
+ + + +<#include '/adminPage/script.html'/> +<#include '/adminPage/select_root.html'/> + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/app.yml b/src/main/resources/app.yml index eff584e3..d5969af6 100644 --- a/src/main/resources/app.yml +++ b/src/main/resources/app.yml @@ -1,5 +1,5 @@ server: - port: 8080 + port: 8081 request: maxBodySize: 20mb maxFileSize: 2048mb @@ -8,7 +8,7 @@ server: project: sqlPrint: false beanPackage: com.cym.model - home: /home/nginxWebUI/ + home: ./home/nginxWebUI/ findPass: false solon: diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 3737951d..9a244c6a 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -310,6 +310,7 @@ mailStr.user = \u7528\u6237\u540D menuStr.about = \u5173\u4E8E menuStr.admin = \u7BA1\u7406\u5458\u7BA1\u7406 +menuStr.sso = SSO menuStr.bak = \u5907\u4EFD\u6587\u4EF6\u7BA1\u7406 menuStr.basic = \u57FA\u672C\u53C2\u6570\u914D\u7F6E menuStr.cert = \u8BC1\u4E66\u7BA1\u7406 diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index a0af07c9..968442ff 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -310,6 +310,7 @@ mailStr.user = Username menuStr.about = About menuStr.admin = Administrator +menuStr.sso = SSO menuStr.bak = Backup menuStr.basic = Basic configuration menuStr.cert = Certificate diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties index 8e96c9fd..622d5eb4 100644 --- a/src/main/resources/messages_zh_TW.properties +++ b/src/main/resources/messages_zh_TW.properties @@ -310,6 +310,7 @@ mailStr.user = \u7528\u6236\u540D menuStr.about = \u95DC\u65BC menuStr.admin = \u7BA1\u7406\u54E1\u7BA1\u7406 +menuStr.sso = SSO menuStr.bak = \u5099\u4EFD\u6587\u4EF6\u7BA1\u7406 menuStr.basic = \u57FA\u672C\u53C3\u6578\u914D\u7F6E menuStr.cert = \u8B49\u66F8\u7BA1\u7406 -- Gitee From e7e07f593234a9ad54f5c7da9f94296d3442b41e Mon Sep 17 00:00:00 2001 From: indsvr <2394857693@qq.com> Date: Mon, 30 Jun 2025 17:39:52 +0800 Subject: [PATCH 2/3] SSO-OAuth2.0 --- pom.xml | 6 + src/main/java/com/cym/config/AppFilter.java | 3 + .../controller/adminPage/SSOController.java | 188 ++++++------------ .../WEB-INF/view/adminPage/login/index.html | 1 + .../WEB-INF/view/adminPage/sso/index.html | 86 +++----- 5 files changed, 104 insertions(+), 180 deletions(-) diff --git a/pom.xml b/pom.xml index 89d11f83..232fb557 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,12 @@ expiringmap 0.5.11 + + + com.jayway.jsonpath + json-path + 2.6.0 + diff --git a/src/main/java/com/cym/config/AppFilter.java b/src/main/java/com/cym/config/AppFilter.java index 1e3f1af2..9553deca 100644 --- a/src/main/java/com/cym/config/AppFilter.java +++ b/src/main/java/com/cym/config/AppFilter.java @@ -171,6 +171,9 @@ public class AppFilter implements Filter { if (ctx.path().toLowerCase().contains("adminPage/login".toLowerCase())) { return true; } + if (ctx.path().toLowerCase().contains("adminPage/sso".toLowerCase())) { + return true; + } String creditKey = ctx.param("creditKey"); boolean isCredit = creditService.check(creditKey); diff --git a/src/main/java/com/cym/controller/adminPage/SSOController.java b/src/main/java/com/cym/controller/adminPage/SSOController.java index b44c02ee..d7159305 100644 --- a/src/main/java/com/cym/controller/adminPage/SSOController.java +++ b/src/main/java/com/cym/controller/adminPage/SSOController.java @@ -1,6 +1,10 @@ package com.cym.controller.adminPage; +import cn.hutool.core.lang.UUID; import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.cym.ext.AdminExt; import com.cym.ext.Tree; import com.cym.model.Admin; @@ -9,16 +13,15 @@ import com.cym.service.AdminService; import com.cym.service.GroupService; import com.cym.service.SettingService; import com.cym.sqlhelper.bean.Page; -import com.cym.utils.AuthUtils; -import com.cym.utils.BaseController; -import com.cym.utils.JsonResult; -import com.cym.utils.SendMailUtils; +import com.cym.sqlhelper.utils.ConditionAndWrapper; +import com.cym.utils.*; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; +import com.jayway.jsonpath.JsonPath; import org.noear.solon.annotation.Controller; import org.noear.solon.annotation.Inject; import org.noear.solon.annotation.Mapping; @@ -49,148 +52,85 @@ public class SSOController extends BaseController { @Mapping("") public ModelAndView index(ModelAndView modelAndView) { - modelAndView.put("page", ""); + + modelAndView.put("codeUrl", settingService.get("sso_codeUrl")); + modelAndView.put("tokenUrl", settingService.get("sso_tokenUrl")); + modelAndView.put("userinfoUrl", settingService.get("sso_userinfoUrl")); + modelAndView.put("jsonpath", settingService.get("sso_jsonpath")); + modelAndView.put("clientID", settingService.get("sso_clientID")); + modelAndView.put("clientSecret", settingService.get("sso_clientSecret")); modelAndView.view("/adminPage/sso/index.html"); return modelAndView; } - @Mapping("addOver") - public JsonResult addOver(String id, String name, Boolean api, Integer type, String[] parentId) { - - if (StrUtil.isEmpty(id)) { - Long count = adminService.getCountByName(name); - if (count > 0) { - return renderError(m.get("adminStr.nameRepetition")); - } - } else { - Long count = adminService.getCountByNameWithOutId(name, id); - if (count > 0) { - return renderError(m.get("adminStr.nameRepetition")); - } - } - - Admin admin = new Admin(); - admin.setId(id); - admin.setName(name); - admin.setApi(api); - admin.setType(type); - - adminService.addOver(admin, parentId); + @Mapping("save") + public JsonResult save(String codeUrl, String tokenUrl, String userinfoUrl, String jsonpath, String clientID, String clientSecret,String callbackUrl) { + + settingService.set("sso_codeUrl",codeUrl); + settingService.set("sso_tokenUrl",tokenUrl); + settingService.set("sso_userinfoUrl",userinfoUrl); + settingService.set("sso_jsonpath",jsonpath); + settingService.set("sso_clientID",clientID); + settingService.set("sso_clientSecret",clientSecret); + settingService.set("sso_callbackUrl",callbackUrl); return renderSuccess(); } - @Mapping("changePassOver") - public JsonResult changePassOver(String id, String pass, Boolean auth) { - Admin admin = new Admin(); - admin.setId(id); - admin.setPass(pass); - admin.setAuth(auth); + @Mapping("redirect") + public void redirect(Context ctx) { - adminService.changePassOver(admin); - return renderSuccess(); - } + String codeUrl= settingService.get("sso_codeUrl"); + String clientID=settingService.get("sso_clientID"); + String callbackUrl=settingService.get("sso_callbackUrl"); + + String url = codeUrl+ "?client_id="+clientID+"&response_type=code&redirect_uri="+callbackUrl+"&oauth_timestamp="+System.currentTimeMillis()+"&state="; - @Mapping("detail") - public JsonResult detail(String id) { - AdminExt adminExt = new AdminExt(); - adminExt.setAdmin(sqlHelper.findById(id, Admin.class)); - adminExt.setGroupIds(adminService.getGroupIds(adminExt.getAdmin().getId())); - adminExt.getAdmin().setPass(""); - return renderSuccess(adminExt); + ctx.redirect(url); } - @Mapping("del") - public JsonResult del(String id) { - String[] ids = id.split(","); - sqlHelper.deleteByIds(ids, Admin.class); + @Mapping("code") + public void code(String code,Context ctx) { - return renderSuccess(); - } - - - - - @Mapping("getMailSetting") - public JsonResult getMailSetting() { - Map map = new HashMap<>(); - - map.put("mail_host", settingService.get("mail_host")); - map.put("mail_port", settingService.get("mail_port")); - map.put("mail_from", settingService.get("mail_from")); - map.put("mail_user", settingService.get("mail_user")); - map.put("mail_pass", settingService.get("mail_pass")); - map.put("mail_ssl", settingService.get("mail_ssl")); - map.put("mail_interval", settingService.get("mail_interval")); - - return renderSuccess(map); - } + String tokenUrl=settingService.get("sso_tokenUrl"); + String userinfoUrl=settingService.get("sso_userinfoUrl"); + String jsonpath=settingService.get("sso_jsonpath"); + String clientID=settingService.get("sso_clientID"); + String clientSecret=settingService.get("sso_clientSecret"); + String callbackUrl=settingService.get("sso_callbackUrl"); - @Mapping("updateMailSetting") - public JsonResult updateMailSetting(String mailType, String mail_user, String mail_host, String mail_port, String mail_from, String mail_pass, String mail_ssl, String mail_interval) { - settingService.set("mail_host", mail_host); - settingService.set("mail_port", mail_port); - settingService.set("mail_user", mail_user); - settingService.set("mail_from", mail_from); - settingService.set("mail_pass", mail_pass); - settingService.set("mail_ssl", mail_ssl); - settingService.set("mail_interval", mail_interval); - return renderSuccess(); - } + String getTokenUrl = tokenUrl + "?grant_type=authorization_code&oauth_timestamp="+System.currentTimeMillis()+"&client_id="+clientID+"&client_secret="+clientSecret + +"&code="+code+"&redirect_uri="+callbackUrl; - @Mapping("testMail") - public JsonResult testMail(String mail) { - if (StrUtil.isEmpty(mail)) { - return renderError(m.get("adminStr.emailEmpty")); - } - try { - sendCloudUtils.sendMailSmtp(mail, m.get("adminStr.emailTest"), m.get("adminStr.emailTest")); - return renderSuccess(); - } catch (Exception e) { - logger.error(e.getMessage(), e); - return renderError(m.get("commonStr.error") + ": " + e.getMessage()); - } - } + String post = HttpUtil.post(getTokenUrl, ""); - @Mapping("testAuth") - public JsonResult testAuth(String key, String code) { + JSONObject entries = JSONUtil.parseObj(post); + String accessToken = entries.getStr("access_token"); - Boolean rs = authUtils.testKey(key, code); - return renderSuccess(rs); - } + String userInfoUrl = userinfoUrl+"?access_token="+accessToken; - @Mapping(value = "qr") - public void getqcode(String url, Integer w, Integer h) throws IOException { - if (StrUtil.isNotBlank(url)) { - - if (w == null) { - w = 300; - } - if (h == null) { - h = 300; - } - try { - Hashtable hints = new Hashtable(); - hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); - hints.put(EncodeHintType.MARGIN, 0); - - BitMatrix matrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, w, h, hints); - MatrixToImageWriter.writeToStream(matrix, "png", Context.current().outputStream()); - } catch (WriterException e) { - logger.error(e.getMessage(), e); - } - } - } + String userinfoStr = HttpUtil.get(userInfoUrl); + +// +// +// JSONObject jsonObject = JSONUtil.parseObj(userinfoStr); + + String read = JsonPath.read(userinfoStr, jsonpath); + + Admin admin = sqlHelper.findOneByQuery(new ConditionAndWrapper().eq(Admin::getName, read), Admin.class); + + admin.setAutoKey(UUID.randomUUID().toString()); // 生成自动登录code + sqlHelper.updateById(admin); + + Context.current().sessionSet("localType", "local"); + Context.current().sessionSet("isLogin", true); + Context.current().sessionSet("admin", admin); + Context.current().sessionRemove("imgCode"); // 立刻销毁验证码 - @Mapping("getGroupTree") - public JsonResult getGroupTree() { - List groups = groupService.getListByParent(null); - List treeList = new ArrayList<>(); - remoteController.fillTree(groups, treeList); - return renderSuccess(treeList); + ctx.redirect("/adminPage/monitor"); } } diff --git a/src/main/resources/WEB-INF/view/adminPage/login/index.html b/src/main/resources/WEB-INF/view/adminPage/login/index.html index 6b91ca9d..d56ff158 100644 --- a/src/main/resources/WEB-INF/view/adminPage/login/index.html +++ b/src/main/resources/WEB-INF/view/adminPage/login/index.html @@ -46,6 +46,7 @@
+ ${menuStr.sso}
diff --git a/src/main/resources/WEB-INF/view/adminPage/sso/index.html b/src/main/resources/WEB-INF/view/adminPage/sso/index.html index 7b92ed91..50d156b7 100644 --- a/src/main/resources/WEB-INF/view/adminPage/sso/index.html +++ b/src/main/resources/WEB-INF/view/adminPage/sso/index.html @@ -47,114 +47,88 @@
- -
- +
- +
- +
-

jsonpath表达式获取用户唯一信息,例如:$.a.b

+

jsonpath表达式获取用户唯一信息,例如:$.a.b; 所得值需等于《用户名》

- +
- +
- +
-

SSO Server会携带code访问下方地址(下方地址?code=xxxxxxx),例如:http://host/callback?code=xxxxxxx

- +
- - +
-
-
- - -
- - - -<#include '/adminPage/script.html'/> -<#include '/adminPage/select_root.html'/> - - - - - + -- Gitee From cb801d224b213f6aea9f2af4660f3ededb39c09a Mon Sep 17 00:00:00 2001 From: indsvr <2394857693@qq.com> Date: Tue, 1 Jul 2025 09:03:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?SSO-OAuth2.0=20ui=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/WEB-INF/view/adminPage/sso/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/resources/WEB-INF/view/adminPage/sso/index.html b/src/main/resources/WEB-INF/view/adminPage/sso/index.html index 50d156b7..195f965a 100644 --- a/src/main/resources/WEB-INF/view/adminPage/sso/index.html +++ b/src/main/resources/WEB-INF/view/adminPage/sso/index.html @@ -46,6 +46,9 @@
+
+ SSO-OAuth2.0配置 +
@@ -108,6 +111,14 @@
+ + +<#include '/adminPage/script.html'/> +<#include '/adminPage/select_root.html'/> + + + +