Skip to content

Commit f695941

Browse files
committed
feat!: 升级项目使用sa-token认证
1 parent 87da5b0 commit f695941

23 files changed

+922
-751
lines changed

database/migration_sa_token.sql

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
-- ============================================================
2+
-- Sa-Token 认证系统重构 - 数据库迁移脚本
3+
-- 创建时间: 2025-12-01
4+
-- 说明: 创建sys_user_auth表并迁移现有微信数据
5+
-- ============================================================
6+
7+
-- ============================================================
8+
-- 步骤1: 创建用户第三方认证表
9+
-- 功能: 支持一个用户绑定多个第三方平台(微信/QQ/支付宝等)
10+
-- ============================================================
11+
CREATE TABLE IF NOT EXISTS `sys_user_auth` (
12+
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
13+
`user_id` INT NOT NULL COMMENT '用户ID,关联sys_user.user_id',
14+
`open_id` VARCHAR(100) NOT NULL COMMENT '第三方平台的唯一标识(如微信openid)',
15+
`union_id` VARCHAR(100) DEFAULT NULL COMMENT '微信unionid(用于同一主体的不同应用)',
16+
`platform` VARCHAR(20) NOT NULL COMMENT '平台标识: wechat/qq/alipay/apple等',
17+
`profile` TEXT DEFAULT NULL COMMENT '第三方返回的原始JSON数据',
18+
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
19+
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
20+
PRIMARY KEY (`id`),
21+
INDEX `idx_user_id` (`user_id`),
22+
INDEX `idx_open_id` (`open_id`),
23+
INDEX `idx_user_platform` (`user_id`, `platform`),
24+
UNIQUE KEY `uk_platform_openid` (`platform`, `open_id`)
25+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户第三方认证信息表';
26+
27+
-- ============================================================
28+
-- 步骤2: 迁移现有微信数据到新表
29+
-- ============================================================
30+
INSERT INTO sys_user_auth (user_id, open_id, union_id, platform, profile)
31+
SELECT
32+
user_id,
33+
wx_open_id AS open_id,
34+
wx_union_id AS union_id,
35+
'wechat' AS platform,
36+
JSON_OBJECT(
37+
'openid', wx_open_id,
38+
'unionid', wx_union_id,
39+
'migrated', true,
40+
'migrate_time', NOW()
41+
) AS profile
42+
FROM sys_user
43+
WHERE wx_open_id IS NOT NULL AND wx_open_id != '';
44+
45+
-- ============================================================
46+
-- 步骤3: 验证数据迁移
47+
-- ============================================================
48+
SELECT
49+
'原始微信数据数量' AS description,
50+
COUNT(*) AS count
51+
FROM sys_user
52+
WHERE wx_open_id IS NOT NULL AND wx_open_id != ''
53+
UNION ALL
54+
SELECT
55+
'迁移后数据数量' AS description,
56+
COUNT(*) AS count
57+
FROM sys_user_auth
58+
WHERE platform = 'wechat';
59+
60+
-- ============================================================
61+
-- 注意事项:
62+
-- 1. 本脚本会保留sys_user表的wx_open_id和wx_union_id字段
63+
-- 2. 稳定运行1-2周后,可以选择删除这些字段
64+
-- 3. 删除前请先备份数据库
65+
-- 4. 删除命令(暂不执行):
66+
-- ALTER TABLE sys_user DROP COLUMN wx_open_id;
67+
-- ALTER TABLE sys_user DROP COLUMN wx_union_id;
68+
-- ============================================================

pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,19 @@
282282
<artifactId>netty-all</artifactId>
283283
<version>4.1.110.Final</version>
284284
</dependency>
285+
<!-- Sa-Token -->
286+
<dependency>
287+
<groupId>cn.dev33</groupId>
288+
<artifactId>sa-token-spring-boot3-starter</artifactId>
289+
<version>1.39.0</version>
290+
</dependency>
291+
292+
<!-- Sa-Token Redis集成 (使用Jackson序列化) -->
293+
<dependency>
294+
<groupId>cn.dev33</groupId>
295+
<artifactId>sa-token-redis-jackson</artifactId>
296+
<version>1.39.0</version>
297+
</dependency>
285298
</dependencies>
286299

287300
<build>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.xiaozhi.common.config;
2+
3+
import com.xiaozhi.service.SysUserService;
4+
import com.xiaozhi.utils.AuthUtils;
5+
import jakarta.annotation.PostConstruct;
6+
import jakarta.annotation.Resource;
7+
import org.springframework.context.annotation.Configuration;
8+
9+
/**
10+
* 认证工具类配置
11+
*
12+
* @author Joey
13+
*/
14+
@Configuration
15+
public class AuthUtilsConfig {
16+
17+
@Resource
18+
private SysUserService userService;
19+
20+
@PostConstruct
21+
public void init() {
22+
AuthUtils.setUserService(userService);
23+
}
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.xiaozhi.common.config;
2+
3+
import cn.dev33.satoken.interceptor.SaInterceptor;
4+
import cn.dev33.satoken.stp.StpUtil;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
7+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8+
9+
/**
10+
* Sa-Token 配置类
11+
*
12+
* @author Joey
13+
*/
14+
@Configuration
15+
public class SaTokenConfig implements WebMvcConfigurer {
16+
17+
/**
18+
* 注册Sa-Token拦截器
19+
*/
20+
@Override
21+
public void addInterceptors(InterceptorRegistry registry) {
22+
// 注册Sa-Token拦截器,拦截所有API请求
23+
// 不需要登录的接口请使用 @SaIgnore 注解标注
24+
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
25+
.addPathPatterns("/api/**");
26+
}
27+
}

src/main/java/com/xiaozhi/common/config/WebMvcConfig.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.xiaozhi.common.config;
22

3-
import com.xiaozhi.common.interceptor.AuthenticationInterceptor;
43
import com.xiaozhi.common.interceptor.LogInterceptor;
54

65
import lombok.extern.slf4j.Slf4j;
@@ -23,26 +22,8 @@ public class WebMvcConfig implements WebMvcConfigurer { // 实现接口而不
2322
@Resource
2423
private LogInterceptor logInterceptor;
2524

26-
@Resource
27-
private AuthenticationInterceptor authenticationInterceptor;
28-
2925
@Override
3026
public void addInterceptors(InterceptorRegistry registry) {
31-
registry.addInterceptor(authenticationInterceptor)
32-
.addPathPatterns("/**")
33-
.excludePathPatterns(
34-
"/api/user/login",
35-
"/api/user/register",
36-
"/api/device/ota",
37-
"/audio/**",
38-
"/uploads/**",
39-
"/ws/**",
40-
// 添加 swagger 相关路径
41-
"/swagger-ui/**",
42-
"/v3/api-docs/**",
43-
"/swagger-resources/**",
44-
"/webjars/**"
45-
);
4627
}
4728

4829
@Override

src/main/java/com/xiaozhi/common/exception/GlobalExceptionHandler.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.xiaozhi.common.exception;
22

3+
import cn.dev33.satoken.exception.NotLoginException;
4+
import cn.dev33.satoken.exception.NotPermissionException;
5+
import cn.dev33.satoken.exception.NotRoleException;
36
import org.slf4j.Logger;
47
import org.slf4j.LoggerFactory;
58
import org.springframework.http.HttpStatus;
@@ -55,6 +58,36 @@ public ResultMessage handleUnauthorizedException(UnauthorizedException e, WebReq
5558
return ResultMessage.error(HttpStatus.FORBIDDEN.value(), e.getMessage());
5659
}
5760

61+
/**
62+
* Sa-Token 未登录异常
63+
*/
64+
@ExceptionHandler(NotLoginException.class)
65+
@ResponseStatus(HttpStatus.UNAUTHORIZED)
66+
public ResultMessage handleNotLoginException(NotLoginException e, WebRequest request) {
67+
logger.warn("用户未登录或token已失效: {}", e.getMessage());
68+
return ResultMessage.error(HttpStatus.UNAUTHORIZED.value(), "登录已过期,请重新登录");
69+
}
70+
71+
/**
72+
* Sa-Token 权限不足异常
73+
*/
74+
@ExceptionHandler(NotPermissionException.class)
75+
@ResponseStatus(HttpStatus.FORBIDDEN)
76+
public ResultMessage handleNotPermissionException(NotPermissionException e, WebRequest request) {
77+
logger.warn("权限不足: {}", e.getMessage());
78+
return ResultMessage.error(HttpStatus.FORBIDDEN.value(), "权限不足");
79+
}
80+
81+
/**
82+
* Sa-Token 角色不足异常
83+
*/
84+
@ExceptionHandler(NotRoleException.class)
85+
@ResponseStatus(HttpStatus.FORBIDDEN)
86+
public ResultMessage handleNotRoleException(NotRoleException e, WebRequest request) {
87+
logger.warn("角色权限不足: {}", e.getMessage());
88+
return ResultMessage.error(HttpStatus.FORBIDDEN.value(), "角色权限不足");
89+
}
90+
5891
/**
5992
* 资源不存在异常
6093
*/

0 commit comments

Comments
 (0)