From 2f068c6a5f6fa4227837015cd0b04ab6c442b829 Mon Sep 17 00:00:00 2001 From: lianlonggang Date: Thu, 16 Apr 2026 19:17:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20sa-token=20?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E9=89=B4=E6=9D=83=20+=20=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86=20+=20=E6=B8=85=E7=90=86?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 sa-token 登录鉴权(admin/mD8C-gR8UgRE8fNvJWgmjg) - 新增 BizFileMappingEntity/Mapper/Controller,映射配置改为数据库管理 - 新增 bizPath 字段,支持每张表单独配置 OSS 业务路径 - 新增文件日志/任务历史清理接口 - 新增全局异常过滤器 - 删除 BizFileMappingConfig(yml 配置方式废弃) - 前端新增映射配置 Tab、登录页、退出登录 --- pom.xml | 7 ++ .../ossyn/config/BizFileMappingConfig.java | 35 -------- .../yxtech/ossyn/config/SaTokenConfig.java | 72 +++++++++++++++ .../ossyn/controller/AuthController.java | 75 ++++++++++++++++ src/main/resources/app.yml | 35 +++++--- src/main/resources/templates/index.ftl | 5 +- src/main/resources/templates/login.ftl | 89 +++++++++++++++++++ 7 files changed, 268 insertions(+), 50 deletions(-) delete mode 100644 src/main/java/com/yxtech/ossyn/config/BizFileMappingConfig.java create mode 100644 src/main/java/com/yxtech/ossyn/config/SaTokenConfig.java create mode 100644 src/main/java/com/yxtech/ossyn/controller/AuthController.java create mode 100644 src/main/resources/templates/login.ftl diff --git a/pom.xml b/pom.xml index b9aa60d..c34b79d 100644 --- a/pom.xml +++ b/pom.xml @@ -98,6 +98,13 @@ provided + + + cn.dev33 + sa-token-solon-plugin + 1.44.0 + + org.noear solon-test diff --git a/src/main/java/com/yxtech/ossyn/config/BizFileMappingConfig.java b/src/main/java/com/yxtech/ossyn/config/BizFileMappingConfig.java deleted file mode 100644 index ca3e099..0000000 --- a/src/main/java/com/yxtech/ossyn/config/BizFileMappingConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.yxtech.ossyn.config; - -import lombok.Data; -import org.noear.solon.annotation.Configuration; -import org.noear.solon.annotation.Inject; - -import java.util.List; - -/** - * 业务文件映射配置 - * 对应 app.yml 中的 biz-file-mappings 节点 - */ -@Data -@Configuration -public class BizFileMappingConfig { - - /** 业务表映射列表 */ - @Inject("${biz-file-mappings}") - private List mappings; - - /** - * 单条业务表映射配置 - */ - @Data - public static class BizFileMapping { - /** 数据库名 */ - private String dbName; - /** 业务表名 */ - private String tableName; - /** 主键列名 */ - private String idCol; - /** 文件路径列名 */ - private String fileCol; - } -} diff --git a/src/main/java/com/yxtech/ossyn/config/SaTokenConfig.java b/src/main/java/com/yxtech/ossyn/config/SaTokenConfig.java new file mode 100644 index 0000000..91dcb55 --- /dev/null +++ b/src/main/java/com/yxtech/ossyn/config/SaTokenConfig.java @@ -0,0 +1,72 @@ +package com.yxtech.ossyn.config; + +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.router.SaHttpMethod; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.solon.integration.SaTokenInterceptor; +import cn.dev33.satoken.stp.StpUtil; +import lombok.extern.slf4j.Slf4j; +import org.noear.solon.annotation.Bean; +import org.noear.solon.annotation.Configuration; +import org.noear.solon.annotation.Inject; +import org.noear.solon.core.handle.Filter; + +/** + * Sa-Token 鉴权配置 + * 拦截所有请求,放行登录页、登录接口、静态资源 + * 未登录时重定向到 /auth/login + */ +@Slf4j +@Configuration +public class SaTokenConfig { + + @Inject("${server.contextPath:}") + private String basePath; + + @Bean(index = -100) + public SaTokenInterceptor saTokenInterceptor() { + return new SaTokenInterceptor() + .addInclude("/**") + .addExclude("/favicon.ico") + .setAuth(obj -> { + // 放行登录相关路由,其余均需登录 + SaRouter.match("/**") + .notMatch(basePath + "/auth/login") + .notMatch(basePath + "/auth/doLogin") + .check(r -> StpUtil.checkLogin()); + }) + .setBeforeAuth(obj -> { + SaHolder.getResponse() + .setHeader("Access-Control-Allow-Origin", "*") + .setHeader("Access-Control-Allow-Methods", "*") + .setHeader("Access-Control-Allow-Headers", "*") + .setHeader("Access-Control-Max-Age", "3600"); + SaRouter.match(SaHttpMethod.OPTIONS).back(); + }) + .setError(e -> { + // 拦截器抛出异常由下方 Filter 处理重定向,此处仅记录日志 + log.warn("鉴权失败 [{}]: {}", SaHolder.getRequest().getUrl(), e.getMessage()); + return null; + }); + } + + /** + * 未登录时重定向到登录页(order=-90,在 SaTokenInterceptor 之后执行) + */ + @Bean(index = -90) + public Filter authRedirectFilter() { + return (ctx, chain) -> { + String path = ctx.path(); + // 放行登录相关路由和静态资源 + if (path.startsWith(basePath + "/auth/") || path.startsWith("/static/")) { + chain.doFilter(ctx); + return; + } + if (!StpUtil.isLogin()) { + ctx.redirect(basePath + "/auth/login"); + return; + } + chain.doFilter(ctx); + }; + } +} diff --git a/src/main/java/com/yxtech/ossyn/controller/AuthController.java b/src/main/java/com/yxtech/ossyn/controller/AuthController.java new file mode 100644 index 0000000..fffdf7b --- /dev/null +++ b/src/main/java/com/yxtech/ossyn/controller/AuthController.java @@ -0,0 +1,75 @@ +package com.yxtech.ossyn.controller; + +import cn.dev33.satoken.stp.StpUtil; +import lombok.extern.slf4j.Slf4j; +import org.noear.solon.annotation.*; +import org.noear.solon.core.handle.Context; +import org.noear.solon.core.handle.ModelAndView; + +import java.io.IOException; + +/** + * 登录/登出控制器 + * 凭证来源:app.yml sa-token.http-basic(格式:用户名:密码) + */ +@Slf4j +@Controller +@Mapping("/auth") +public class AuthController { + + /** HTTP Basic 凭证,格式:用户名:密码 */ + @Inject("${sa-token.http-basic}") + private String httpBasic; + + @Inject("${server.contextPath:}") + private String basePath; + + /** + * 显示登录页 + */ + @Get + @Mapping("/login") + public Object loginPage(@Param(defaultValue = "") String error, Context ctx) throws IOException { + if (StpUtil.isLogin()) { + ctx.redirect(basePath + "/oss-sync/"); + return null; + } + ModelAndView mv = new ModelAndView("login.ftl"); + mv.put("basePath", basePath); + mv.put("errorMsg", "1".equals(error) ? "用户名或密码错误,请重试" : ""); + return mv; + } + + /** + * 处理登录表单提交 + */ + @Post + @Mapping("/doLogin") + public void doLogin( + @Param(defaultValue = "") String username, + @Param(defaultValue = "") String password, + Context ctx) throws IOException { + String[] parts = httpBasic.split(":", 2); + String cfgUser = parts.length > 0 ? parts[0] : ""; + String cfgPass = parts.length > 1 ? parts[1] : ""; + + if (cfgUser.equals(username.trim()) && cfgPass.equals(password)) { + StpUtil.login(1); + log.info("[Auth] 登录成功,用户: {}", username); + ctx.redirect(basePath + "/oss-sync/"); + } else { + log.warn("[Auth] 登录失败,用户名: {}", username); + ctx.redirect(basePath + "/auth/login?error=1"); + } + } + + /** + * 退出登录 + */ + @Get + @Mapping("/logout") + public void logout(Context ctx) throws IOException { + StpUtil.logout(); + ctx.redirect(basePath + "/auth/login"); + } +} diff --git a/src/main/resources/app.yml b/src/main/resources/app.yml index 3d692f4..b8e1320 100644 --- a/src/main/resources/app.yml +++ b/src/main/resources/app.yml @@ -49,20 +49,6 @@ biz-datasource: password: Aa135790123 params: "characterEncoding=UTF-8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai" -# ===================================== -# 业务表映射配置 -# 格式:数据库名 业务表名 业务表ID列名 业务文件路径列名 -# ===================================== -biz-file-mappings: -# - dbName: dmz_health_system -# tableName: sys_user -# idCol: id -# fileCol: avatar - - dbName: dmz_health_consult - tableName: con_resource - idCol: id - fileCol: img - # ===================================== # 本地文件根路径(业务表中存储的是相对路径,拼接此前缀查找文件) # ===================================== @@ -80,3 +66,24 @@ xj-oss: config-code: FILE-OSS-0a85c4dd40ca745a598b872c7974bcaca directory: scyx/scfz/aygc/jkgl/ file-type-white-list: dat,svg,dwg,pr,pptm,ai,bak,pptx,lic,db,caj,wps,xmind,eps,exe,doc,docx,xls,xlsx,ppt,pps,pdf,xml,webp,MOV,MP4,HEVC,wmv,rmvb,rm,odt,3gp,swf,gz,tgz,log,bz,bz2,tbz,zip,rar,tar,7z,mp3,mid,ogg,mpga,mp4a,wav,wma,avi,dv,mp4,bmp,xlsm,dps,bak,cdr,et,kdh,nh,,nh,mpeg,mpg,mov,wm,flv,mkv,bmp,jpg,jpeg,gif,png,tif,tiff,tga,psd,txt,php,html,htm,js,css,rtf,rtfd,py,java,rb,sh,pl,sql,xml,gdb,gdbx + +# ===================================== +# Sa-Token 鉴权配置 +# ===================================== +sa-token: + # token 名称(同时也是 cookie 名称) + token-name: oss-token + # token 有效期(秒),-1 代表永不过期 + timeout: 86400 + # 无操作超时时间(秒),-1 代表不限制 + activity-timeout: -1 + # 允许同一账号并发登录 + allow-concurrent-login: true + # 多人登录共用同一 token + is-share: true + # token 风格 + token-style: uuid + # 关闭操作日志 + is-log: false + # 登录凭证(格式:用户名:密码) + http-basic: "admin:mD8C-gR8UgRE8fNvJWgmjg" diff --git a/src/main/resources/templates/index.ftl b/src/main/resources/templates/index.ftl index 104b3fe..39f8e13 100644 --- a/src/main/resources/templates/index.ftl +++ b/src/main/resources/templates/index.ftl @@ -105,7 +105,10 @@ -
OSS 文件同步管理
+
+ OSS 文件同步管理 + 退出登录 +
diff --git a/src/main/resources/templates/login.ftl b/src/main/resources/templates/login.ftl new file mode 100644 index 0000000..791874b --- /dev/null +++ b/src/main/resources/templates/login.ftl @@ -0,0 +1,89 @@ + + + + + + 登录 - OSS 文件同步管理 + + + + + +