# 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依赖。