注意,LangChat 的权限使用了 Sa-Token,核心配置位于 /langchat-llm-ops/langchat-llm-auth 和 /langchat-common/langchat-common-ai
系统架构概述
LangChat Pro 采用基于 Sa-Token 的权限认证系统,实现了完整的用户认证、权限控制和会话管理功能。系统支持多种认证方式,包括用户名密码、JWT Token 等,并提供了灵活的权限控制机制。
权限模块结构
认证配置
请求头 Token 配置
因为 Sa-Token 有默认的请求头名称,一般情况我们采用 Authorization 作为请求头认证 Key,具体配置如下:
因此,访问的认证请求头如下:
Authorization: Bearer xxxxxx
认证流程
Redis 配置
会话存储配置
登录后,登录信息配置在 Redis 中,因此可以轻松的实现过期配置,相关的 Key 设置如下:
Redis 配置示例
spring:
redis:
host: localhost
port: 6379
database: 0
timeout: 10000ms
lettuce:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
Sa-Token Redis 配置
sa-token:
# Token 名称
token-name: Authorization
# Token 有效期
timeout: 2592000
# Token 临时有效期
activity-timeout: -1
# 是否允许同一账号并发登录
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 Token
is-share: false
# Token 风格
token-style: uuid
# 是否输出操作日志
is-log: false
# 是否从 Cookie 中读取 Token
is-read-cookie: false
# 是否从 Header 中读取 Token
is-read-header: true
# 是否从 Body 中读取 Token
is-read-body: false
请求拦截配置
拦截器配置
common 目录下放的是 Auth 相关抽离的公共配置,而应用具体的拦截配置如下:
拦截器实现示例
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 获取请求路径
String requestURI = request.getRequestURI();
// 白名单路径直接放行
if (isWhitePath(requestURI)) {
return true;
}
// 验证 Token
String token = request.getHeader("Authorization");
if (StringUtils.isEmpty(token)) {
throw new UnauthorizedException("Token 不能为空");
}
// 验证 Token 有效性
if (!StpUtil.isLogin()) {
throw new UnauthorizedException("Token 无效");
}
// 权限验证
if (!hasPermission(requestURI)) {
throw new ForbiddenException("权限不足");
}
return true;
}
}
白名单配置
auth:
white-list:
- /auth/login
- /auth/register
- /public/**
- /swagger-ui/**
- /v3/api-docs/**
日志监听配置
对于 LLM 项目,日志文件会存储在 aigc_log 表中
日志配置示例
logging:
level:
com.langchat.auth: DEBUG
com.langchat.security: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/auth.log
max-size: 100MB
max-history: 30
权限接口
认证接口
核心接口说明
权限控制实现
注解权限控制
@RestController
@RequestMapping("/api")
public class UserController {
@SaCheckPermission("user:list")
@GetMapping("/users")
public Result<List<User>> getUserList() {
// 需要 user:list 权限
return Result.success(userService.list());
}
@SaCheckRole("admin")
@PostMapping("/users")
public Result<User> createUser(@RequestBody User user) {
// 需要 admin 角色
return Result.success(userService.save(user));
}
}
编程式权限控制
@Service
public class UserService {
public void deleteUser(Long userId) {
// 检查是否有删除用户的权限
if (!StpUtil.hasPermission("user:delete")) {
throw new ForbiddenException("权限不足");
}
// 检查是否是删除自己
if (StpUtil.getLoginIdAsLong().equals(userId)) {
throw new ForbiddenException("不能删除自己");
}
userMapper.deleteById(userId);
}
}
安全最佳实践
1. Token 安全
- 使用 HTTPS 传输
- 设置合理的过期时间
- 实现 Token 刷新机制
- 支持 Token 黑名单
2. 密码安全
- 密码加密存储(BCrypt)
- 密码复杂度要求
- 登录失败次数限制
- 密码定期更换提醒
3. 权限最小化
- 遵循最小权限原则
- 定期审查用户权限
- 实现权限审计日志
- 支持动态权限调整
完成以上配置后,系统将具备完整的权限认证和访问控制能力。