ソースを参照

bump: 发布1.6.0

* chore: 更新至 1.6.0; 更新初始数据库 schema

* pref: 不要直接提示“账号不存在”或“密码不正确”,避免撞库攻击

* docs: 补充注释

* docs: 升级至 Spring Boot 2.7.x

* feat: 绑定用户与角色关联关系后,用户会被强制踢下线

* docs: 补充注释 & pref: 优化代码

* bump: 发布1.6.0
Uncarbon 4 年 前
コミット
60cb4b5cd0

+ 1 - 1
README.md

@@ -1,7 +1,7 @@
 # helio-boot
 
 ## 项目介绍
-`helio-boot`基于 Spring Boot 2.6.x,是一款预置SaaS、RBAC能力的单体项目脚手架,适合初学者学习、老手接外包干私活、初创企业快速上马项目
+`helio-boot`基于 Spring Boot 2.7.x,是一款预置SaaS、RBAC能力的单体项目脚手架,适合初学者学习、老手接外包干私活、初创企业快速上马项目
 
 JDK compatibility: 1.8 - 17
 

+ 1 - 1
attachments/schema/MySQL/helio_boot.sql

@@ -153,7 +153,7 @@ VALUES (1, 0, 1, 0, '2021-06-01 17:16:48', NULL, '2021-06-02 17:14:16', NULL, '
        (4, 0, 1, 0, '2021-06-01 17:14:47', NULL, '2021-06-02 11:32:23', NULL, '工作台', 2, 1, 'Dashboard:workbench',
         'ant-design:database-outlined', 2, 1, '/dashboard/workbench/index', ''),
        (5, 0, 1, 0, '2021-06-01 17:15:38', NULL, '2021-07-15 23:56:43', 'admin', '关于', 0, 1, 'About',
-        'ant-design:eye-outlined', 2, 1, '/sys/vben/about/index', ''),
+        'ant-design:eye-outlined', 2, 1, '/sys/about/index', ''),
        (6, 0, 1, 0, '2021-06-02 16:06:58', NULL, '2021-07-17 23:55:52', 'admin', '学(mo)习(yu)', 2, 3, '',
         'ant-design:zhihu-outlined', 3, 1, 'https://www.zhihu.com/', 'https://www.zhihu.com/'),
        (7, 0, 1, 0, '2021-07-17 23:32:15', NULL, '2021-07-17 23:32:15', NULL, '部门管理', 1, 1, 'SysDept',

+ 1 - 1
attachments/schema/PostgreSQL/helio_boot.sql

@@ -258,7 +258,7 @@ VALUES (4, 0, 1, 0, '2021-06-01 17:14:47', NULL, '2021-06-02 11:32:23', NULL, '
         'ant-design:database-outlined', 2, 1, '/dashboard/workbench/index', '');
 INSERT INTO "sys_menu"
 VALUES (5, 0, 1, 0, '2021-06-01 17:15:38', NULL, '2021-07-15 23:56:43', 'admin', '关于', 0, 1, 'About',
-        'ant-design:eye-outlined', 2, 1, '/sys/vben/about/index', '');
+        'ant-design:eye-outlined', 2, 1, '/sys/about/index', '');
 INSERT INTO "sys_menu"
 VALUES (6, 0, 1, 0, '2021-06-02 16:06:58', NULL, '2021-07-17 23:55:52', 'admin', '学(mo)习(yu)', 2, 3, '',
         'ant-design:zhihu-outlined', 3, 1, 'https://www.zhihu.com/', 'https://www.zhihu.com/');

+ 3 - 2
pom.xml

@@ -7,11 +7,12 @@
     <parent>
         <groupId>cc.uncarbon.framework</groupId>
         <artifactId>helio-starters</artifactId>
-        <version>1.5.1</version>
+        <version>1.6.0</version>
     </parent>
 
     <artifactId>helio-boot</artifactId>
-    <version>1.5.1</version>
+    <!-- 程序版本号,建议每次打包发布时都调整以作区分 -->
+    <version>1.6.0</version>
 
     <properties>
     </properties>

+ 2 - 2
src/main/java/cc/uncarbon/interceptor/AdminSaTokenParseInterceptor.java

@@ -45,8 +45,8 @@ public class AdminSaTokenParseInterceptor implements AsyncHandlerInterceptor {
             TenantContextHolder.setTenantContext(tenantContext);
 
         } else {
-            UserContextHolder.setUserContext(null);
-            TenantContextHolder.setTenantContext(null);
+            UserContextHolder.clear();
+            TenantContextHolder.clear();
         }
 
         return true;

+ 1 - 3
src/main/java/cc/uncarbon/module/sys/enums/SysErrorEnum.java

@@ -15,9 +15,7 @@ public enum SysErrorEnum implements HelioBaseEnum<Integer> {
 
     INVALID_ID(400, "无效ID"),
 
-    USER_NOT_EXISTS(400, "用户不存在"),
-
-    INCORRECT_USER_PASSWORD(400, "密码不正确"),
+    INCORRECT_PIN_OR_PWD(400, "账号或密码不正确"),
 
     BANNED_USER(400, "用户被封禁"),
 

+ 3 - 2
src/main/java/cc/uncarbon/module/sys/service/SysUserService.java

@@ -184,13 +184,14 @@ public class SysUserService extends HelioBaseServiceImpl<SysUserMapper, SysUserE
             TenantContextHolder.setTenantContext(tenantContext);
         }
 
+        // 不要直接提示“账号不存在”或“密码不正确”,避免撞库攻击
         SysUserEntity sysUserEntity = this.getUserByPin(dto.getUsername());
         if (sysUserEntity == null) {
-            throw new BusinessException(SysErrorEnum.USER_NOT_EXISTS);
+            throw new BusinessException(SysErrorEnum.INCORRECT_PIN_OR_PWD);
         }
 
         if (!PwdUtil.encrypt(dto.getPassword(), sysUserEntity.getSalt()).equals(sysUserEntity.getPwd())) {
-            throw new BusinessException(SysErrorEnum.INCORRECT_USER_PASSWORD);
+            throw new BusinessException(SysErrorEnum.INCORRECT_PIN_OR_PWD);
         }
 
         if (SysUserStatusEnum.BANNED.equals(sysUserEntity.getStatus())) {

+ 4 - 1
src/main/java/cc/uncarbon/module/sys/util/AdminStpUtil.java

@@ -12,7 +12,10 @@ import lombok.experimental.UtilityClass;
 import java.util.List;
 
 /**
- * 自定义的StpUtil,用于后台管理
+ * 后台管理专用 StpUtil
+ * 文档见 SA-Token -> 多账户认证
+ * https://sa-token.dev33.cn/doc/index.html#/up/many-account
+ *
  * @author Uncarbon
  */
 @UtilityClass

+ 8 - 5
src/main/java/cc/uncarbon/module/sys/web/auth/AdminAuthController.java

@@ -6,7 +6,6 @@ import cc.uncarbon.framework.core.context.TenantContext;
 import cc.uncarbon.framework.core.context.TenantContextHolder;
 import cc.uncarbon.framework.core.context.UserContext;
 import cc.uncarbon.framework.core.context.UserContextHolder;
-import cc.uncarbon.framework.core.exception.BusinessException;
 import cc.uncarbon.framework.web.model.response.ApiResult;
 import cc.uncarbon.helper.CaptchaHelper;
 import cc.uncarbon.helper.RolePermissionCacheHelper;
@@ -20,7 +19,6 @@ import cc.uncarbon.module.sys.service.SysUserService;
 import cc.uncarbon.module.sys.util.AdminStpUtil;
 import cn.dev33.satoken.annotation.SaCheckLogin;
 import cn.hutool.captcha.AbstractCaptcha;
-import cn.hutool.core.lang.Assert;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
@@ -95,8 +93,8 @@ public class AdminAuthController {
     @PostMapping(value = "/logout")
     public ApiResult<?> logout() {
         AdminStpUtil.logout();
-        UserContextHolder.setUserContext(null);
-        TenantContextHolder.setTenantContext(null);
+        UserContextHolder.clear();
+        TenantContextHolder.clear();
 
         return ApiResult.success();
     }
@@ -105,7 +103,12 @@ public class AdminAuthController {
     @ApiImplicitParam(name = "uuid", value = "验证码图片UUID", required = true)
     @GetMapping(value = "/captcha")
     public void captcha(HttpServletResponse response, String uuid) throws IOException {
-        Assert.notBlank(uuid, () -> new BusinessException(SysErrorEnum.UUID_CANNOT_BE_BLANK));
+        /*
+        由前端定义 UUID 其实并不算太好的办法,但是够简单
+        更复杂而安全的做法是:由后端生成一个 UUID,通过响应头返回给前端(这对前端有一定的技能技术要求)
+         */
+        // uuid 为空则抛出异常
+        SysErrorEnum.UUID_CANNOT_BE_BLANK.assertNotBlank(uuid);
 
         // 核验方法:captchaHelper.validate(uuid, true);
         AbstractCaptcha captcha = captchaHelper.generate(uuid);

+ 6 - 0
src/main/java/cc/uncarbon/module/sys/web/sys/AdminSysUserController.java

@@ -124,6 +124,12 @@ public class AdminSysUserController {
     @PostMapping(value = "/bindRoles")
     public ApiResult<?> bindRoles(@RequestBody @Valid AdminBindUserRoleRelationDTO dto) {
         sysUserService.adminBindRoles(dto);
+        // 该用户会被强制踢下线,以更新对应权限;可以视业务需要决定是否删除该代码
+        this.kickOut(
+                AdminKickOutSysUserDTO.builder()
+                        .userId(dto.getUserId())
+                        .build()
+        );
 
         return ApiResult.success();
     }

+ 1 - 1
src/main/resources/application-dev.yml

@@ -25,7 +25,7 @@ spring:
     host: 127.0.0.1
     # Redis连接端口
     port: 6379
-    # Redis登录密码
+    # Redis登录密码;如果没有设置密码,请注释掉下面这行,避免向 Redis-server 发送 AUTH 鉴权请求,引发程序启动失败
     password:
     # Redis数据库序号
     database: 1

+ 6 - 0
src/main/resources/application.yml

@@ -74,6 +74,7 @@ logging:
     # 指定日志级别,开发、测试环境建议为 DEBUG,生产环境建议为 INFO
     cc.uncarbon: DEBUG
 
+# 详细配置文档:https://sa-token.dev33.cn/doc/index.html#/use/config
 sa-token:
   # token名称
   token-name: Authorization
@@ -87,3 +88,8 @@ sa-token:
   is-read-body: false
   # 是否尝试从cookie里读取token
   is-read-cookie: false
+  # 有效期解释:https://sa-token.dev33.cn/doc/index.html#/fun/token-timeout
+  # token 有效期,单位=秒;默认30天,-1代表永不过期
+  timeout: 2592000
+  # token 临时有效期 (指定时间内无操作就视为token过期),单位=秒
+  activity-timeout: -1