# fast-security
**Repository Path**: zxyd/fast-security
## Basic Information
- **Project Name**: fast-security
- **Description**: 基于 Spring Security 的快速使用框架。
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2023-11-17
- **Last Updated**: 2023-11-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 项目说明
本项目完全基于 `Spring Security`,只针对日常开发项目中的认证、动态权限需求做一层封装,干净纯洁。
可用于项目快速开发、`Spring Security` 框架学习。
另鉴于 JWT 目前用的最多,内置封装逻辑为,认证成功后生成 token 返回。
token 中包含 userId、roleIds。
Token 内容示例:
```
{
alg: "HS256"
}.
{
roles: "10,1,5",
exp: 1626480624,
userId: "1"
}.
[signature]
```
## 包说明
```
├─authentication 鉴权相关处理
├─authorization 认证相关处理
├─config Security配置
├─constant 常量
├─filter 全局过滤器(登录入口、JWT 处理入口)
├─handle 认证、鉴权结果处理器
├─loginlogic 登录逻辑
│ └─base
├─model 实体
└─utils 工具类
```
## 快速使用
1. 引入依赖
此包未发布到中央仓库,请自行安装至本地仓库。
```xml
pri.damai
fast-security
0.0.1-SNAPSHOT
```
2. 提供用户查询接口。
```java
@Component
public class UserServiceImpl{
static List userList = new ArrayList<>();
static {
FastUserInfo one = new FastUserInfo();
one.setId("1");
one.setPhone("123456");
one.setUsername("xxx");
one.setPassword("xxxx");
ArrayList oneRoles = new ArrayList<>();
oneRoles.add("10");
one.setRoleList(oneRoles);
FastUserInfo two = new FastUserInfo();
two.setId("2");
two.setPhone("54321");
two.setUsername("yyyy");
two.setPassword("xxxx");
ArrayList twoRoles = new ArrayList<>();
twoRoles.add("5");
two.setRoleList(twoRoles);
FastUserInfo three = new FastUserInfo();
three.setId("3");
three.setPhone("0997876");
three.setUsername("bbbb");
three.setPassword("xxxx");
ArrayList threeRoles = new ArrayList<>();
threeRoles.add("1");
three.setRoleList(threeRoles);
userList.add(one);
userList.add(two);
userList.add(three);
}
public FastUserInfo loadUserByPhone(String phone) {
return userList.stream()
.filter(user -> user.getPhone().equals(phone))
.findAny()
.orElseThrow(() -> new AuthenticationServiceException("无此用户"));
}
}
```
3. 实现登录逻辑
```java
@Component
public class PhoneLogin extends AbstractLoginLogic {
@Resource
UserServiceImpl userService;
@Override
public String getSupportLoginType() {
return "phone";
}
@Override
public void checkParam(LoginData loginData) throws AuthenticationException {
String msg = null;
if (loginData.getPhone() == null) {
msg = "手机号不可为空";
}
if (loginData.getPhoneVerifyCode() == null) {
msg = msg + ", 短信验证码不可为空";
}
if (!Objects.equals(msg, null)) {
this.throwException(msg);
}
}
@Override
protected void login(LoginData loginData) throws AuthenticationException {
if (!"22".equals(loginData.getPhoneVerifyCode())) {
this.throwException("验证码错误");
}
// 具体登录逻辑
FastUserInfo fastUserInfo = this.getUserDetails(loginData);
}
@Override
public FastUserInfo getUserDetails(LoginData loginData) {
return userService.loadUserByPhone(loginData.getPhone());
}
private void throwException(String msg) {
throw new AuthenticationServiceException(msg);
}
}
```
4. 实现 `ResourceService` 接口 。通过此接口,提供权限查询功能。
```java
@Component
public class MyResourceImpl implements ResourceService {
static HashMap> roleMap = new HashMap<>();
static {
String superAdmin = "10";
String admin = "5";
String user = "1";
ArrayList superAdminUrlRoleIds = new ArrayList<>();
superAdminUrlRoleIds.add(superAdmin);
superAdminUrlRoleIds.add(admin);
superAdminUrlRoleIds.add(user);
roleMap.put("/superAdmin", superAdminUrlRoleIds);
ArrayList adminUrlRoleIds = new ArrayList<>();
adminUrlRoleIds.add(admin);
adminUrlRoleIds.add(user);
roleMap.put("/admin", adminUrlRoleIds);
ArrayList userUrlRoleIds = new ArrayList<>();
userUrlRoleIds.add(admin);
userUrlRoleIds.add(user);
roleMap.put("/user", userUrlRoleIds);
}
@Override
public List getRolesByUrl(String url) {
return roleMap.get(url);
}
}
```
## 其他扩展功能
### 可选 yml 配置
以下配置均有默认值,有指定要求时再配置即可。
```yaml
fast-security:
not-login-urls: # 指定无需登录即可访问的接口
- /user
login-url: # 指定登录接口的url
expiration: # 指定 token 过期时间
jwt-secret: # 指定 Jwt 密匙
authentication-failed-code: # 指定登录失败错误码
unauthorized-code: # 指定未认证错误码
permission-denied-code: # 指定未授权错误码
no-roles-pass: # 未配置Url时,是否直接放行
```
### 登录成功处理器
在实际开发中,我们可能需要存储 token。可实现 `LoginSuccessResultHandler` 接口来自定义功能。
```java
@Component
public class GGLoginSuccessResultHandler implements LoginSuccessResultHandler {
@Override
public Object handleResult(UserDetails userDetails, String token) {
// 保存 token or 其他操作
return null;
}
}
```
### 自定义登录失败处理器
```java
@Component
public class GGLoginFailureResultHandler implements LoginFailureResultHandler {
@Override
public Object handleResult(AuthenticationException e) {
return null;
}
}
```
## 总体流程说明
### 首次登录流程
```mermaid
graph TD
A(登录请求) --> B(MyAuthenticationProcessingFilter) --> C(MyAuthenticationTokenProvider)
--> D{AbstractLoginLogic}
D --> |无异常| D1(MyAuthenticationSuccessHandler) --> D2(LoginSuccessResultHandler) --> D3[登录成功]
D --> |有异常| D4(MyAuthenticationFailureHandler) --> D5(LoginFailureResultHandler) --> D6[登录失败]
```
### 业务请求
```mermaid
graph TD
A(业务请求) --> B(JwtFilter) --> C(MySecurityMetadataSource)
--> D(MyAccessDecisionManager) --> E{异常}
E --> |有异常| E1[业务请求失败, 无权访问]
E --> |无异常| E2(鉴权成功) --> E3[处理业务]
```