SDK使用指南¶
📦 SDK介绍¶
auth-spring-boot-starter 是一个开箱即用的Spring Boot Starter,可以让你的应用快速集成认证授权功能。
核心功能¶
- ✅ 自动配置认证拦截器
- ✅ 注解式权限控制
- ✅ Token自动续期
- ✅ 用户上下文自动注入
- ✅ 统一异常处理
- ✅ 请求头自动传递
🚀 快速开始¶
1. 添加依赖¶
<dependency>
<groupId>cn.zhangziming</groupId>
<artifactId>auth-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
2. 配置文件¶
auth:
# 认证服务器配置
server:
url: http://localhost:8080 # 认证服务地址
timeout: 5000 # 超时时间(毫秒)
# OAuth客户端配置
client:
id: your-client-id # 客户端ID
secret: your-client-secret # 客户端密钥
# Token配置
token:
header-name: Authorization # Token请求头名称
prefix: Bearer # Token前缀
auto-refresh: true # 是否自动刷新Token
refresh-threshold: 300 # 刷新阈值(秒)
# 拦截器配置
interceptor:
enabled: true # 是否启用拦截器
exclude-paths: # 排除路径
- /public/**
- /static/**
- /actuator/**
# 权限配置
permission:
enabled: true # 是否启用权限验证
cache-enabled: true # 是否缓存权限
cache-time: 1800 # 缓存时间(秒)
# 租户配置
tenant:
enabled: false # 是否启用多租户
header-name: X-Tenant-Id # 租户ID请求头名称
3. 启用自动配置¶
@SpringBootApplication
@EnableAuthClient // 启用认证客户端
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
🎯 注解使用¶
@RequireLogin - 登录验证¶
用于标记需要登录才能访问的接口。
@RestController
@RequestMapping("/api")
public class ApiController {
// 单个接口需要登录
@RequireLogin
@GetMapping("/user/info")
public Result getUserInfo() {
UserInfo user = UserContext.getCurrentUser();
return Result.success(user);
}
// 整个Controller需要登录
@RequireLogin
@RestController
@RequestMapping("/api/protected")
public class ProtectedController {
// 所有接口都需要登录
}
}
@RequirePermission - 权限验证¶
用于标记需要特定权限才能访问的接口。
@RestController
@RequestMapping("/api/user")
public class UserController {
// 需要单个权限
@RequirePermission("user:read")
@GetMapping("/list")
public Result list() {
return Result.success();
}
// 需要多个权限(AND关系)
@RequirePermission(value = {"user:read", "user:export"}, logical = Logical.AND)
@GetMapping("/export")
public Result export() {
return Result.success();
}
// 需要任意一个权限(OR关系)
@RequirePermission(value = {"user:read", "user:write"}, logical = Logical.OR)
@GetMapping("/view/{id}")
public Result view(@PathVariable Long id) {
return Result.success();
}
}
@RequireRole - 角色验证¶
用于标记需要特定角色才能访问的接口。
@RestController
@RequestMapping("/api/admin")
public class AdminController {
// 需要单个角色
@RequireRole("ADMIN")
@DeleteMapping("/user/{id}")
public Result deleteUser(@PathVariable Long id) {
return Result.success();
}
// 需要多个角色(AND关系)
@RequireRole(value = {"ADMIN", "SUPER_ADMIN"}, logical = Logical.AND)
@PostMapping("/system/config")
public Result updateConfig() {
return Result.success();
}
// 需要任意一个角色(OR关系)
@RequireRole(value = {"ADMIN", "MANAGER"}, logical = Logical.OR)
@GetMapping("/reports")
public Result reports() {
return Result.success();
}
}
@IgnoreAuth - 忽略认证¶
用于在需要认证的Controller中排除某些接口。
@RestController
@RequestMapping("/api/user")
@RequireLogin // 整个Controller需要登录
public class UserController {
// 这个接口不需要登录
@IgnoreAuth
@PostMapping("/register")
public Result register(@RequestBody RegisterDTO dto) {
return Result.success();
}
// 其他接口需要登录
@GetMapping("/profile")
public Result profile() {
return Result.success();
}
}
🔧 核心API¶
UserContext - 用户上下文¶
获取当前登录用户信息。
@Service
public class BusinessService {
public void doSomething() {
// 获取当前用户完整信息
UserInfo user = UserContext.getCurrentUser();
// 获取用户ID
Long userId = UserContext.getUserId();
// 获取用户名
String username = UserContext.getUsername();
// 获取租户ID
String tenantId = UserContext.getTenantId();
// 获取用户角色
List<String> roles = UserContext.getRoles();
// 获取用户权限
List<String> permissions = UserContext.getPermissions();
// 检查是否有某个权限
boolean hasPermission = UserContext.hasPermission("user:read");
// 检查是否有某个角色
boolean hasRole = UserContext.hasRole("ADMIN");
// 清除当前上下文(一般不需要手动调用)
UserContext.clear();
}
}
AuthClient - 认证客户端¶
直接调用认证服务的API。
@Service
public class UserService {
@Autowired
private AuthClient authClient;
// 登录
public LoginResponse login(String username, String password) {
return authClient.login(username, password);
}
// 登出
public void logout(String token) {
authClient.logout(token);
}
// 刷新Token
public TokenResponse refreshToken(String refreshToken) {
return authClient.refreshToken(refreshToken);
}
// 验证Token
public boolean validateToken(String token) {
return authClient.validateToken(token);
}
// 获取用户信息
public UserInfoResponse getUserInfo(String token) {
return authClient.getUserInfo(token);
}
// 检查用户权限
public boolean checkPermission(Long userId, String permission) {
return authClient.checkPermission(userId, permission);
}
// 获取用户权限列表
public List<String> getUserPermissions(Long userId) {
return authClient.getUserPermissions(userId);
}
}
PermissionService - 权限服务¶
编程式权限验证。
@Service
public class OrderService {
@Autowired
private PermissionService permissionService;
public void deleteOrder(Long orderId) {
// 检查当前用户是否有删除权限
if (!permissionService.hasPermission("order:delete")) {
throw new PermissionException("无权限删除订单");
}
// 检查是否有任意一个权限
if (permissionService.hasAnyPermission("order:delete", "order:admin")) {
// 执行删除
}
// 检查是否有所有权限
if (permissionService.hasAllPermissions("order:read", "order:delete")) {
// 执行操作
}
// 检查角色
if (permissionService.hasRole("ADMIN")) {
// 执行操作
}
}
}
TokenManager - Token管理器¶
管理Token的生命周期。
@Service
public class TokenService {
@Autowired
private TokenManager tokenManager;
public void manageToken() {
// 获取当前Token
String token = tokenManager.getCurrentToken();
// 刷新Token
TokenResponse newToken = tokenManager.refreshToken();
// 验证Token是否有效
boolean isValid = tokenManager.validateToken(token);
// 获取Token过期时间
Long expireTime = tokenManager.getTokenExpireTime(token);
// 检查Token是否即将过期
boolean willExpire = tokenManager.willExpireSoon(token, 300);
// 撤销Token(登出)
tokenManager.revokeToken(token);
}
}
🔌 扩展点¶
自定义权限验证器¶
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(UserInfo user, String permission) {
// 自定义权限验证逻辑
// 示例:超级管理员拥有所有权限
if (user.getRoles().contains("SUPER_ADMIN")) {
return true;
}
// 示例:从数据库或缓存查询权限
return userPermissionRepository.hasPermission(user.getUserId(), permission);
}
@Override
public boolean hasRole(UserInfo user, String role) {
// 自定义角色验证逻辑
return user.getRoles().contains(role);
}
}
自定义Token提取器¶
@Component
public class CustomTokenExtractor implements TokenExtractor {
@Override
public String extractToken(HttpServletRequest request) {
// 从Header提取
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
return token.substring(7);
}
// 从Cookie提取
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("access_token".equals(cookie.getName())) {
return cookie.getValue();
}
}
}
// 从URL参数提取
return request.getParameter("token");
}
}
自定义异常处理¶
@ControllerAdvice
public class AuthExceptionHandler {
@ExceptionHandler(AuthenticationException.class)
public ResponseEntity<Result> handleAuthenticationException(AuthenticationException e) {
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.body(Result.error(401, "认证失败: " + e.getMessage()));
}
@ExceptionHandler(PermissionException.class)
public ResponseEntity<Result> handlePermissionException(PermissionException e) {
return ResponseEntity
.status(HttpStatus.FORBIDDEN)
.body(Result.error(403, "权限不足: " + e.getMessage()));
}
@ExceptionHandler(TokenExpiredException.class)
public ResponseEntity<Result> handleTokenExpiredException(TokenExpiredException e) {
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.body(Result.error(1003, "Token已过期"));
}
}
自定义拦截器¶
@Component
public class CustomAuthInterceptor extends AuthInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 调用父类的认证逻辑
boolean authenticated = super.preHandle(request, response, handler);
if (authenticated) {
// 自定义逻辑,例如记录访问日志
logAccess(request);
}
return authenticated;
}
private void logAccess(HttpServletRequest request) {
UserInfo user = UserContext.getCurrentUser();
log.info("用户 {} 访问了 {}", user.getUsername(), request.getRequestURI());
}
}
🎨 高级特性¶
多租户支持¶
// 启用多租户
@Configuration
@EnableMultiTenant
public class TenantConfig {
@Bean
public TenantResolver tenantResolver() {
return new HeaderTenantResolver("X-Tenant-Id");
}
}
// 使用租户信息
@Service
public class DataService {
public void queryData() {
String tenantId = UserContext.getTenantId();
// 根据租户ID查询数据
}
}
数据权限¶
// 数据权限注解
@DataPermission(type = DataScopeType.DEPT)
@GetMapping("/list")
public Result list() {
// 自动根据用户的数据权限过滤数据
return Result.success();
}
// 自定义数据权限
@DataPermission(
type = DataScopeType.CUSTOM,
sqlFilter = "dept_id IN (SELECT dept_id FROM user_dept WHERE user_id = #{userId})"
)
@GetMapping("/dept-users")
public Result deptUsers() {
return Result.success();
}
缓存策略¶
// 配置缓存
@Configuration
public class CacheConfig {
@Bean
public PermissionCache permissionCache() {
return new RedisPermissionCache(redisTemplate);
}
}
// 清除用户缓存
@Service
public class UserService {
@Autowired
private PermissionCache permissionCache;
public void updateUserPermissions(Long userId) {
// 更新权限后清除缓存
permissionCache.evict(userId);
}
}
异步权限加载¶
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public AsyncPermissionLoader asyncPermissionLoader() {
return new AsyncPermissionLoader();
}
}
// 使用异步加载
@Service
public class PermissionService {
@Autowired
private AsyncPermissionLoader permissionLoader;
@Async
public CompletableFuture<List<String>> loadUserPermissions(Long userId) {
return permissionLoader.load(userId);
}
}
🧪 测试支持¶
单元测试¶
@SpringBootTest
@AutoConfigureMockAuthClient // 自动配置Mock认证客户端
public class ServiceTest {
@Autowired
private UserService userService;
@Test
@WithMockUser(username = "admin", roles = {"ADMIN"}, permissions = {"user:read"})
public void testGetUser() {
// 模拟登录用户
UserInfo user = UserContext.getCurrentUser();
assertEquals("admin", user.getUsername());
assertTrue(UserContext.hasRole("ADMIN"));
}
@Test
@WithMockUser(userId = 1L, username = "test")
public void testBusinessLogic() {
// 测试业务逻辑
Long userId = UserContext.getUserId();
assertEquals(1L, userId);
}
}
集成测试¶
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureAuthClient
public class ControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private MockAuthServer mockAuthServer; // Mock认证服务器
@Test
public void testProtectedEndpoint() {
// 模拟登录获取Token
String token = mockAuthServer.mockLogin("admin", "admin123");
// 携带Token访问接口
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(token);
HttpEntity<?> entity = new HttpEntity<>(headers);
ResponseEntity<Result> response = restTemplate.exchange(
"/api/user/info",
HttpMethod.GET,
entity,
Result.class
);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
}
📝 最佳实践¶
1. 权限粒度设计¶
// 推荐:使用细粒度权限
@RequirePermission("user:create") // 创建用户
@RequirePermission("user:read") // 查询用户
@RequirePermission("user:update") // 更新用户
@RequirePermission("user:delete") // 删除用户
// 不推荐:权限粒度过粗
@RequirePermission("user") // 太粗,不够灵活
2. 异常处理¶
@Service
public class UserService {
public void deleteUser(Long userId) {
// 方式一:使用注解(推荐)
// @RequirePermission("user:delete")
// 方式二:手动检查
if (!UserContext.hasPermission("user:delete")) {
throw new PermissionException("无权限删除用户");
}
// 业务逻辑
}
}
3. 性能优化¶
// 启用权限缓存
auth.permission.cache-enabled=true
// 批量加载权限
@Service
public class PermissionService {
@Cacheable(value = "user-permissions", key = "#userId")
public List<String> getUserPermissions(Long userId) {
return authClient.getUserPermissions(userId);
}
}
4. 安全建议¶
// 1. 使用HTTPS传输
// 2. 定期刷新Token
// 3. 敏感操作二次验证
// 4. 记录审计日志
@Service
@Slf4j
public class SensitiveOperationService {
@RequirePermission("system:config:update")
@AuditLog(operation = "更新系统配置", level = AuditLevel.HIGH)
public void updateSystemConfig(ConfigDTO config) {
// 敏感操作,记录日志
log.warn("用户 {} 更新了系统配置", UserContext.getUsername());
// 执行更新
}
}
🔗 相关资源¶
需要帮助? 查看完整文档或联系技术支持