# coufran-spring-boot-starter-auth **Repository Path**: coufran/coufran-spring-boot-starter-auth ## Basic Information - **Project Name**: coufran-spring-boot-starter-auth - **Description**: Spring starter,权限 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-05-24 - **Last Updated**: 2023-03-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: Spring, SpringBoot, 权限控制, lib ## README # 用法 ## 基础用法 ### 启用权限拦截 引入依赖即可启用权限拦截,默认拦截所有请求。 ```xml cn.coufran coufran-spring-boot-starter-auth 1.3.0 ``` ### 切换认证方式 使用``@EnableAuthXxxx``切换认证方式。例如: ```java @Configuration @EnableAuthSession // 启用Session认证 //@EnableAuthToken // 启用Token认证 public class AuthConfig { } ``` | 认证方式 | 启用注解 | 说明 | |-----------|------------------------|----------------------| | Session认证 | ``@EnableAuthSession`` | 使用Session和Cookie实现认证 | | Token认证 | ``@EnableAuthToken`` | 使用Token实现认证 | ### 标记公共接口 使用``@Public``注解标记公共接口,公共接口不会被拦截。例如: ```java @RestController public class OpenController { @ReqeustMapping("/demo") @Public // 标记公共接口 public void demo() { } } ``` ### 与权限拦截交互 所有的交互都是通过``AuthUser``完成的。可以使用Spring注入``AuthUser``的方式与其交互,``AuthUser``方法如下: 1. **登录**:``AuthUser.login(data)``,data为保存在上下文中的数据。 2. **登出**:``AuthUser.logout()``。 3. **获取保存在上下文的数据**:``AuthUser.getData()``。 4. **是否通过认证**:``AuthUser.isAuthenticated()``。 例如: ```java @RestController public class DemoController { @Resource private AuthUser authUser; @RequestMapping("/demo") public Certificate demo() { Certificate certificate; if (!authUser.isAuthenticated()) { // 判断是否登录(通过认证) certificate = authUser.login(new User("xxx")); // 登录系统 } User user = authUser.getData(); // 访问上下文数据 if (user.autoLogout()) { authUser.logout(); // 登出系统 } return certificate; } } ``` ### 白名单设置 通过配置拦截白名单,可以将某些不需要拦截的请求放行。可以通过配置文件配置``coufran.auth.whitePath``,例如: ```yaml coufran: auth: whitePath: /openPath1, /openPath2, /open/openPath3 ``` ### 自定义权限拦截插件 拦截器默认只实现了未认证用户的拦截,如果需要更高级的拦截功能,可以自定义插件,注入拦截过程。 自定义权限拦截插件的方式如下: 1. 定义类,实现``AuthAddition``接口。 2. 重写``authIntercept(xxx)``方法,需要拦截的请求,抛出``AuthException``。 3. 将插件类使用``@Component``标记为Spring Bean。 例如: ```java @Component public class DemoAuthAddition implements AuthAddition { @Override public void authIntercept(AuthUser authUser, HttpServletRequest request, Object handler) throws AuthException { boolean allowed = false; // do sth. if (!allowed) { // 不允许,进行拦截 throw new AuthException(HttpStatus.FORBIDDEN, Result.error(40300, "测试拦截")); } } } ``` ## 认证方式介绍 权限拦截支持多种认证方式,其中内置了三种认证方式。 ### 简单认证(默认,不推荐) 简单认证无法实现跨请求的认证,请求进入系统默认未认证,只能请求开放接口。 ### Session认证 - 使用``@EnableAuthSession``启用Session认证。 - Session认证基于HTTP容器的Session,将权限数据保存在Session中,实现跨请求的认证。 - 该种方式不支持分布式集群系统。 ### Token认证 - 使用``@EnableAuthToken``启用Token认证。 - Token认证基于Token实现认证,请求是无状态的,所有数据保存在Token中,可实现跨服务的认证。 - 可自定义Token生成规则。 #### 自定义Token注册器 1. 自定义类实现``TokenRegister``接口。 2. 重写``generate(xxx)``和``parse(xxx)``方法。 3. 使用``@Component``声明为Spring Bean。 例如: ```java @Component public class DemoTokenRegister implements TokenRegister { public String generate(String payload, int expireTimeDefault) { // 生成token String token = "xxx"; return token; } public String parse(String accessToken) { // 解析Token,Token过期或解析失败返回null String payload = "xxx"; return payload; } } ``` ## 高级用法 ### 自定义认证方式 如果内置的两种认证方式无法满足您的需求,您可以自定义认证方式或基于内置的认证方式进行扩展。 #### 核心接口介绍 1. ``AuthUser``:该接口提供了登录、登出、获取数据等系统与权限拦截相关的交互方法,Bean scope为request。 2. ``AuthUserManager``:``AuthUser``的登录、登出等操作将委托给``AuthUserManager``,负责创建、管理``AuthUser``。 3. ``Certificate``:访问系统的证书,不同的认证方式证书不同,有可能不需要。 #### 自定义步骤 1. 实现``AuthUser``,建议继承``AbstractAuthUser``,然后在其基础上做定制。 2. 实现``AuthUserManager``。 3. 实现``Certificate``,封装证书。 4. 定义配置,定义``AuthUser``为request scope的Spring Bean,在未认证时创建匿名的,认证时恢复原来的。 5. 建议使用``@EnableAuthXxxx``定义认证方式的启动开关。 ### 自定义Token数据转换器 Token认证时,数据将被固化在Token中,需要使用``TokenPayloadConverter``实现数据和字符串你的转换。 系统自带了一个``PojoJsonTokenPayloadConverter``,可以实现基本POJO数据的转换。 如果需要转换其他数据或者需要自定义转换过程,可以自定义``TokenPayloadConverter``。 ```java @Configuration public class TokenPayloadConverterConfig { @Resource(name = "tokenPayloadConverters") private List> tokenPayloadConverters; @PostConstruct public void configConverter() { // 构造Converter TokenPayloadConverter myConverter = new MyConverter(); // 添加到Converter List中,位置越靠前,优先级越高 tokenPayloadConverters.add(0, myConverter); } } ``` ### 自定义Token存储 当前Refresh Token存储不支持集群,如果需要支持集群,可自定义Token存储。 ```java @Component public class MyRefreshTokenRepository implements RefreshTokenRepository { public void save(String refreshToken, Date expireTime) { // doSth. } public boolean delete(String refreshToken) { // doSth. return true; } } ``` ### 自定义秘钥存储 当前秘钥存储在进程内存中,当应用重启后,会重新生成秘钥,导致现有的Token失效,并且,在集群环境中,秘钥无法同步。 我们为您准备了一个基于文件的存储器``FileKeyStore``,如果需要,可以通过``@Bean``将``FileKeyStore``配置在Spring Bean容器中。 ```java import cn.coufran.springboot.starter.auth.impl.token.KeyStore; import org.springframework.stereotype.Component; @Component public class MyKeyStore implements KeyStore { public void save(byte[] key) { // save key } public byte[] load() { // load key } } ``` > 在创建TokenRegister时,会调用秘钥存储器获取秘钥,如果``load()``方法返回``null``,则会创建新的秘钥并调用``save()``方法保存。 # 历史版本 ## v1.0(2021-06-25) 1. 增加基于Session和Token的认证。 2. 增加开放接口定义。 3. 增加自定义权限拦截。 4. 增加拦截白名单。 ## v1.1(2021-07-13) 1. 增加TokenPayloadConverter转换器,实现自定义解析Token。 2. 增加refreshToken和refresh方法,实现刷新登录状态。 3. 增加refreshTokenRepository。 4. 增加对OPTION请求的支持。 ## v1.2(2021-11-xx) 1. 增加KeyStore,支持Token秘钥存储,重启后Token不再失效。 ## v1.3(2022-05-21) 1. 更换Maven依赖。