827 lines
26 KiB
Markdown
827 lines
26 KiB
Markdown
# datai-salesforce-auth 模块详细文档
|
||
|
||
## 模块概述
|
||
|
||
### 基本信息
|
||
- **模块名称**: datai-salesforce-auth
|
||
- **模块类型**: 认证和会话管理模块
|
||
- **版本**: 1.0.0
|
||
- **Java 版本**: 22
|
||
- **编码**: UTF-8
|
||
|
||
### 功能描述
|
||
datai-salesforce-auth 模块负责 Salesforce 认证和会话管理,提供多种登录方式支持、会话信息缓存、连接工厂等核心功能。该模块是整个 Salesforce 集成体系的基础,为其他模块(Partner、Apex、Metadata、Tooling)提供统一的认证和会话管理能力。
|
||
|
||
### 核心特性
|
||
1. **多种登录方式支持**:OAuth2、Salesforce CLI、Legacy Credential、Session ID
|
||
2. **会话管理**:自动 Session 有效性检查、过期自动刷新
|
||
3. **连接工厂**:统一的连接创建和管理接口
|
||
4. **登录历史**:完整的登录历史记录和查询
|
||
5. **安全特性**:密码加密、敏感信息脱敏、请求频率限制
|
||
6. **多 ORG 类型支持**:支持 source 和 target 两种 ORG 类型
|
||
|
||
## 模块架构
|
||
|
||
### 整体架构图
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Controller 层 │
|
||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||
│ │ LoginController │ │ HistoryController│ │
|
||
│ └────────┬─────────┘ └──────────────────┘ │
|
||
└───────────┼──────────────────────────────────────────────────┘
|
||
│
|
||
┌───────────┼──────────────────────────────────────────────────┐
|
||
│ │ Service 层 │
|
||
│ ┌────────┴────────┐ ┌──────────────────┐ │
|
||
│ │ LoginService │ │ HistoryService │ │
|
||
│ └────────┬────────┘ └──────────────────┘ │
|
||
└───────────┼──────────────────────────────────────────────────┘
|
||
│
|
||
┌───────────┼──────────────────────────────────────────────────┐
|
||
│ │ Strategy 层(策略模式) │
|
||
│ ┌────────┴────────┐ ┌──────────────────┐ │
|
||
│ │StrategyFactory │ │ LoginStrategy │ │
|
||
│ └────────┬────────┘ └────────┬─────────┘ │
|
||
│ │ │ │
|
||
│ ┌────────┴──────────────────┴─────────┐ │
|
||
│ │ LegacyCredential │ OAuth2 │ CLI │ SessionId│ │
|
||
│ └──────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────┘
|
||
│
|
||
┌───────────┼──────────────────────────────────────────────────┐
|
||
│ │ Factory 层(工厂模式) │
|
||
│ ┌────────┴────────┐ ┌──────────────────┐ │
|
||
│ │SessionManager │ │ConnectionFactory│ │
|
||
│ └─────────────────┘ └──────────────────┘ │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 分层说明
|
||
|
||
#### 1. Controller 层
|
||
负责处理 HTTP 请求,提供 REST API 接口。
|
||
|
||
**主要类**:
|
||
- `DataISfLoginController`:登录控制器
|
||
- `DataiSfLoginHistoryController`:登录历史控制器
|
||
- `DataiSfLoginSessionController`:登录会话控制器
|
||
|
||
#### 2. Service 层
|
||
负责业务逻辑处理,协调各个组件完成业务功能。
|
||
|
||
**主要类**:
|
||
- `ISalesforceLoginService`:登录服务接口
|
||
- `SalesforceLoginServiceImpl`:登录服务实现
|
||
- `IDataiSfLoginHistoryService`:登录历史服务接口
|
||
- `IDataiSfLoginSessionService`:登录会话服务接口
|
||
|
||
#### 3. Strategy 层(策略模式)
|
||
负责不同登录方式的实现,使用策略模式支持多种登录方式。
|
||
|
||
**主要类**:
|
||
- `LoginStrategy`:登录策略接口
|
||
- `LoginStrategyFactory`:登录策略工厂
|
||
- `LegacyCredentialLoginStrategy`:传统账密凭证登录策略
|
||
- `OAuth2LoginStrategy`:OAuth2 登录策略
|
||
- `SalesforceCliLoginStrategy`:Salesforce CLI 登录策略
|
||
- `SessionIdLoginStrategy`:Session ID 登录策略
|
||
|
||
#### 4. Factory 层(工厂模式)
|
||
负责连接的创建和管理,使用工厂模式提供统一的连接获取接口。
|
||
|
||
**主要类**:
|
||
- `SessionManager`:会话管理器
|
||
- `ISalesforceConnectionFactory<T>`:连接工厂接口
|
||
- `AbstractConnectionFactory<T>`:连接工厂抽象基类
|
||
|
||
## 核心组件详解
|
||
|
||
### 1. SessionManager(会话管理器)
|
||
|
||
**类路径**: `com.datai.auth.core.SessionManager`
|
||
|
||
**功能描述**:
|
||
负责管理 Salesforce 会话信息,提供 Session ID 和 Instance URL 的获取,支持会话有效性检查和自动重新登录。
|
||
|
||
**核心方法**:
|
||
|
||
```java
|
||
/**
|
||
* 获取当前Salesforce会话信息
|
||
* 如果会话无效,则自动尝试重新登录
|
||
*
|
||
* @param orgType ORG类型(source/target)
|
||
* @return SalesforceLoginResult 会话信息
|
||
*/
|
||
public SalesforceLoginResult getCurrentLoginResult(String orgType)
|
||
|
||
/**
|
||
* 获取SessionId
|
||
*
|
||
* @param orgType ORG类型(source/target)
|
||
* @return 访问令牌
|
||
*/
|
||
public String getCurrentSession(String orgType)
|
||
|
||
/**
|
||
* 获取实例URL
|
||
*
|
||
* @param orgType ORG类型(source/target)
|
||
* @return 实例URL
|
||
*/
|
||
public String getInstanceUrl(String orgType)
|
||
|
||
/**
|
||
* 判断当前会话信息是否有效
|
||
*
|
||
* @param orgType ORG类型(source/target)
|
||
* @return 如果会话有效返回true,否则返回false
|
||
*/
|
||
public boolean isSessionValid(String orgType)
|
||
```
|
||
|
||
**特性**:
|
||
- 自动 Session 有效性检查
|
||
- Session 过期时自动重新登录
|
||
- 支持 source 和 target 两种 ORG 类型
|
||
- 提前 5 分钟判断为过期,预留网络传输时间
|
||
|
||
### 2. ISalesforceConnectionFactory(连接工厂接口)
|
||
|
||
**类路径**: `com.datai.auth.factory.ISalesforceConnectionFactory<T>`
|
||
|
||
**功能描述**:
|
||
定义所有 Salesforce 连接工厂的统一接口,提供连接获取、清除缓存等功能。
|
||
|
||
**核心方法**:
|
||
|
||
```java
|
||
/**
|
||
* 获取连接实例
|
||
* 如果缓存中没有有效的连接,则创建新的连接
|
||
*
|
||
* @param orgType ORG 类型(source 或 target)
|
||
* @return 连接实例
|
||
*/
|
||
T getConnection(String orgType)
|
||
|
||
/**
|
||
* 清除缓存的连接
|
||
* 从缓存中移除连接实例
|
||
*
|
||
* @param orgType ORG 类型(source 或 target)
|
||
*/
|
||
void clearConnection(String orgType)
|
||
|
||
/**
|
||
* 获取连接类型名称
|
||
*
|
||
* @return 连接类型名称
|
||
*/
|
||
String getConnectionType()
|
||
```
|
||
|
||
### 3. AbstractConnectionFactory(连接工厂抽象基类)
|
||
|
||
**类路径**: `com.datai.auth.factory.AbstractConnectionFactory<T>`
|
||
|
||
**功能描述**:
|
||
提供通用的连接缓存和管理逻辑,使用模板方法模式,子类只需实现 `createConnection` 方法。
|
||
|
||
**核心方法**:
|
||
|
||
```java
|
||
/**
|
||
* 获取连接实例
|
||
* 自动处理连接缓存和 Session 有效性检查
|
||
*
|
||
* @param orgType ORG 类型(source 或 target)
|
||
* @return 连接实例
|
||
*/
|
||
@Override
|
||
public T getConnection(String orgType)
|
||
|
||
/**
|
||
* 创建连接(抽象方法,由子类实现)
|
||
*
|
||
* @param orgType ORG 类型
|
||
* @return 连接实例
|
||
*/
|
||
protected abstract T createConnection(String orgType)
|
||
|
||
/**
|
||
* 清除缓存的连接
|
||
*
|
||
* @param orgType ORG 类型
|
||
*/
|
||
@Override
|
||
public void clearConnection(String orgType)
|
||
```
|
||
|
||
**特性**:
|
||
- 连接缓存:使用 ConcurrentHashMap 缓存连接
|
||
- 自动 Session 检查:Session 过期时自动清除缓存
|
||
- 线程安全:使用 ReentrantLock 保证多线程安全
|
||
- 模板方法模式:子类只需实现 createConnection 方法
|
||
|
||
### 4. LoginStrategy(登录策略接口)
|
||
|
||
**类路径**: `com.datai.auth.strategy.LoginStrategy`
|
||
|
||
**功能描述**:
|
||
定义不同登录方式的通用方法,支持策略模式。
|
||
|
||
**核心方法**:
|
||
|
||
```java
|
||
/**
|
||
* 执行登录操作
|
||
*
|
||
* @param request 登录请求
|
||
* @return 登录结果
|
||
*/
|
||
SalesforceLoginResult login(SalesforceLoginRequest request)
|
||
|
||
/**
|
||
* 刷新Session
|
||
*
|
||
* @param refreshToken 刷新Session
|
||
* @param loginType 登录类型
|
||
* @return 新的登录结果
|
||
*/
|
||
SalesforceLoginResult refreshToken(String refreshToken, String loginType)
|
||
|
||
/**
|
||
* 执行登出操作
|
||
*
|
||
* @param sessionId Session ID
|
||
* @param loginType 登录类型
|
||
* @return 登出是否成功
|
||
*/
|
||
boolean logout(String sessionId, String loginType)
|
||
|
||
/**
|
||
* 获取登录类型
|
||
*
|
||
* @return 登录类型
|
||
*/
|
||
String getLoginType()
|
||
```
|
||
|
||
### 5. LoginStrategyFactory(登录策略工厂)
|
||
|
||
**类路径**: `com.datai.auth.strategy.LoginStrategyFactory`
|
||
|
||
**功能描述**:
|
||
负责根据登录类型创建对应的登录策略,使用工厂模式。
|
||
|
||
**核心方法**:
|
||
|
||
```java
|
||
/**
|
||
* 根据登录类型获取对应的登录策略
|
||
*
|
||
* @param loginType 登录类型
|
||
* @return 登录策略实现
|
||
*/
|
||
public LoginStrategy getLoginStrategy(String loginType)
|
||
|
||
/**
|
||
* 获取所有支持的登录类型
|
||
*
|
||
* @return 支持的登录类型列表
|
||
*/
|
||
public List<String> getSupportedLoginTypes()
|
||
```
|
||
|
||
**支持的登录类型**:
|
||
- `legacy_credential`:传统账密凭证登录
|
||
- `oauth2`:OAuth2 登录
|
||
- `salesforce_cli`:Salesforce CLI 登录
|
||
- `session_id`:Session ID 登录
|
||
|
||
### 6. LegacyCredentialLoginStrategy(传统账密凭证登录策略)
|
||
|
||
**类路径**: `com.datai.auth.strategy.impl.LegacyCredentialLoginStrategy`
|
||
|
||
**功能描述**:
|
||
支持使用用户名、密码和安全令牌进行登录,使用 SOAP 登录方式。
|
||
|
||
**核心流程**:
|
||
|
||
1. 验证请求参数(用户名、密码)
|
||
2. 获取 Salesforce 配置(API 版本、环境类型、端点 URL 等)
|
||
3. 构建 SOAP 登录请求
|
||
4. 发送 SOAP 请求到 Salesforce
|
||
5. 解析 SOAP 响应,提取 Session ID 和 Instance URL
|
||
6. 返回登录结果
|
||
|
||
**特性**:
|
||
- 使用 SOAP 协议进行登录
|
||
- 支持自定义登录 URL
|
||
- 自动处理 API 版本和端点 URL
|
||
- XML 转义防止注入攻击
|
||
- 友好的错误消息(中文)
|
||
- 连接超时处理
|
||
|
||
**错误处理**:
|
||
- `LOGIN_MUST_USE_SECURITY_TOKEN`:用户名、密码或安全标记无效,或用户被锁定
|
||
- `INVALID_LOGIN`:用户名或密码错误
|
||
- `INVALID_OPERATION_WITH_EXPIRED_PASSWORD`:密码已过期,请重置密码
|
||
- `USER_LOCKED_OUT`:用户已被锁定,请联系管理员
|
||
- `PASSWORD_EXPIRED`:密码已过期
|
||
- `SERVER_UNAVAILABLE`:服务器暂时不可用,请稍后重试
|
||
- `API_DISABLED_FOR_ORG`:组织的 API 访问已禁用
|
||
|
||
## 数据模型
|
||
|
||
### SalesforceLoginRequest(登录请求)
|
||
|
||
**类路径**: `com.datai.auth.model.domain.SalesforceLoginRequest`
|
||
|
||
**字段说明**:
|
||
|
||
| 字段名 | 类型 | 说明 | 必填 |
|
||
|--------|------|------|------|
|
||
| loginType | String | 登录类型(oauth2、salesforce_cli、legacy_credential、session_id) | 是 |
|
||
| username | String | 用户名 | 否 |
|
||
| password | String | 密码 | 否 |
|
||
| securityToken | String | 安全令牌 | 否 |
|
||
| clientId | String | OAuth 客户端 ID | 否 |
|
||
| clientSecret | String | OAuth 客户端密钥 | 否 |
|
||
| grantType | String | OAuth 授权类型 | 否 |
|
||
| orgAlias | String | Salesforce CLI 组织别名 | 否 |
|
||
| privateKeyPath | String | 私有密钥路径 | 否 |
|
||
| privateKeyPassword | String | 私有密钥密码 | 否 |
|
||
| code | String | OAuth 授权码 | 否 |
|
||
| state | String | OAuth state 参数 | 否 |
|
||
| sessionId | String | Session ID | 否 |
|
||
| loginUrl | String | 登录 URL | 否 |
|
||
| orgType | String | 组织类型(source/target) | 否 |
|
||
|
||
### SalesforceLoginResult(登录结果)
|
||
|
||
**类路径**: `com.datai.auth.model.domain.SalesforceLoginResult`
|
||
|
||
**字段说明**:
|
||
|
||
| 字段名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| success | boolean | 登录状态 |
|
||
| errorCode | String | 错误代码 |
|
||
| errorMessage | String | 错误消息 |
|
||
| sessionId | String | Session ID |
|
||
| refreshToken | String | 刷新令牌(仅 OAuth 流程中存在) |
|
||
| tokenType | String | 令牌类型(默认为 "Bearer") |
|
||
| expiresIn | long | 过期时间(秒) |
|
||
| loginTimestamp | long | 登录时间戳 |
|
||
| expirationTimestamp | long | 过期时间戳 |
|
||
| instanceUrl | String | 实例 URL |
|
||
| metadataServerUrl | String | 元数据服务器 URL |
|
||
| sandbox | boolean | 是否为沙盒环境 |
|
||
| passwordExpired | boolean | 密码是否已过期 |
|
||
| userId | String | 用户 ID |
|
||
| organizationId | String | 组织 ID |
|
||
| orgType | String | 组织类型 |
|
||
| userFullName | String | 用户全名 |
|
||
| userEmail | String | 用户邮箱 |
|
||
| organizationName | String | 组织名称 |
|
||
| language | String | 语言 |
|
||
| timeZone | String | 时区 |
|
||
|
||
**核心方法**:
|
||
|
||
```java
|
||
/**
|
||
* 判断 sessionId 是否有效(基于本地时间估算)
|
||
* 提前 5 分钟判断为过期,以预留网络传输时间
|
||
*/
|
||
public boolean isSessionExpired()
|
||
```
|
||
|
||
### DataiSfLoginHistory(登录历史)
|
||
|
||
**类路径**: `com.datai.auth.model.domain.DataiSfLoginHistory`
|
||
|
||
**功能描述**:
|
||
记录用户的登录历史,包括登录时间、登录类型、Session ID 等信息。
|
||
|
||
**主要字段**:
|
||
- id:主键
|
||
- loginType:登录类型
|
||
- username:用户名
|
||
- sessionIdResult:Session ID(加密存储)
|
||
- instanceUrl:实例 URL
|
||
- userId:用户 ID
|
||
- organizationId:组织 ID
|
||
- orgType:组织类型
|
||
- loginTime:登录时间
|
||
- status:登录状态(success/failed)
|
||
- errorMessage:错误消息
|
||
- createTime:创建时间
|
||
|
||
### DataiSfLoginSession(登录会话)
|
||
|
||
**类路径**: `com.datai.auth.model.domain.DataiSfLoginSession`
|
||
|
||
**功能描述**:
|
||
记录用户的登录会话信息,用于会话管理和查询。
|
||
|
||
**主要字段**:
|
||
- id:主键
|
||
- sessionId:Session ID
|
||
- userId:用户 ID
|
||
- orgType:组织类型
|
||
- loginTime:登录时间
|
||
- lastAccessTime:最后访问时间
|
||
- expireTime:过期时间
|
||
- status:会话状态(active/expired)
|
||
- createTime:创建时间
|
||
|
||
## REST API 接口
|
||
|
||
### 1. 执行登录操作
|
||
|
||
**接口**: `POST /salesforce/login/doLogin`
|
||
|
||
**功能**: 执行 Salesforce 登录操作,支持多种登录方式
|
||
|
||
**请求参数**:
|
||
|
||
```json
|
||
{
|
||
"loginType": "legacy_credential",
|
||
"username": "user@example.com",
|
||
"password": "password",
|
||
"securityToken": "token",
|
||
"orgType": "source"
|
||
}
|
||
```
|
||
|
||
**响应示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "登录成功",
|
||
"data": {
|
||
"success": true,
|
||
"sessionId": "00Dxx0000001Gw2!AQ0AQH...",
|
||
"instanceUrl": "https://yourorg.my.salesforce.com",
|
||
"userId": "005xx0000001Gw2EAS",
|
||
"organizationId": "00Dxx0000001Gw2EAS",
|
||
"orgType": "source",
|
||
"userFullName": "John Doe",
|
||
"userEmail": "john.doe@example.com",
|
||
"organizationName": "Your Organization",
|
||
"language": "en_US",
|
||
"timeZone": "America/Los_Angeles"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 执行登出操作
|
||
|
||
**接口**: `POST /salesforce/login/logout`
|
||
|
||
**功能**: 执行 Salesforce 登出操作,清除本地缓存的 Session 信息
|
||
|
||
**响应示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "登出成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 3. 获取登录历史
|
||
|
||
**接口**: `GET /salesforce/login/history`
|
||
|
||
**功能**: 查询登录历史记录
|
||
|
||
**响应示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "查询成功",
|
||
"data": [
|
||
{
|
||
"id": 1,
|
||
"loginType": "legacy_credential",
|
||
"username": "user@example.com",
|
||
"loginTime": "2026-01-28 10:00:00",
|
||
"status": "success",
|
||
"orgType": "source"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 4. 获取登录会话
|
||
|
||
**接口**: `GET /salesforce/login/session`
|
||
|
||
**功能**: 查询当前登录会话信息
|
||
|
||
**响应示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "查询成功",
|
||
"data": {
|
||
"sessionId": "00Dxx0000001Gw2!AQ0AQH...",
|
||
"userId": "005xx0000001Gw2EAS",
|
||
"orgType": "source",
|
||
"loginTime": "2026-01-28 10:00:00",
|
||
"lastAccessTime": "2026-01-28 10:30:00",
|
||
"expireTime": "2026-01-28 11:00:00",
|
||
"status": "active"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 依赖关系
|
||
|
||
### Maven 依赖
|
||
|
||
```xml
|
||
<dependencies>
|
||
<!-- datai-salesforce-setting:配置管理 -->
|
||
<dependency>
|
||
<groupId>com.datai</groupId>
|
||
<artifactId>datai-salesforce-setting</artifactId>
|
||
</dependency>
|
||
|
||
<!-- datai-cache-redis:Redis 缓存 -->
|
||
<dependency>
|
||
<groupId>com.datai</groupId>
|
||
<artifactId>datai-cache-redis</artifactId>
|
||
<version>${datai.version}</version>
|
||
</dependency>
|
||
|
||
<!-- jakarta.xml.soap-api:SOAP API -->
|
||
<dependency>
|
||
<groupId>jakarta.xml.soap</groupId>
|
||
<artifactId>jakarta.xml.soap-api</artifactId>
|
||
<version>3.0.0</version>
|
||
</dependency>
|
||
|
||
<!-- saaj-impl:SAAJ 实现 -->
|
||
<dependency>
|
||
<groupId>com.sun.xml.messaging.saaj</groupId>
|
||
<artifactId>saaj-impl</artifactId>
|
||
<version>3.0.2</version>
|
||
</dependency>
|
||
|
||
<!-- commons-text:Apache Commons Text -->
|
||
<dependency>
|
||
<groupId>org.apache.commons</groupId>
|
||
<artifactId>commons-text</artifactId>
|
||
<version>1.10.0</version>
|
||
</dependency>
|
||
|
||
<!-- jbcrypt:BCrypt 密码加密 -->
|
||
<dependency>
|
||
<groupId>org.mindrot</groupId>
|
||
<artifactId>jbcrypt</artifactId>
|
||
<version>0.4</version>
|
||
</dependency>
|
||
</dependencies>
|
||
```
|
||
|
||
### 模块依赖
|
||
|
||
**被依赖的模块**:
|
||
- datai-salesforce-partner:使用 SessionManager 和连接工厂
|
||
- datai-salesforce-apex:使用 SessionManager 和连接工厂
|
||
- datai-salesforce-metadata:使用 SessionManager 和连接工厂
|
||
- datai-salesforce-tooling:使用 SessionManager 和连接工厂
|
||
|
||
**依赖的模块**:
|
||
- datai-salesforce-setting:配置管理
|
||
- datai-cache-redis:Redis 缓存
|
||
- datai-salesforce-common:通用工具和异常类
|
||
|
||
## 设计模式
|
||
|
||
### 1. 策略模式(Strategy Pattern)
|
||
|
||
**应用场景**:登录策略
|
||
|
||
**实现方式**:
|
||
- `LoginStrategy` 接口定义登录策略的通用方法
|
||
- `LegacyCredentialLoginStrategy`、`OAuth2LoginStrategy`、`SalesforceCliLoginStrategy`、`SessionIdLoginStrategy` 实现具体的登录策略
|
||
- `LoginStrategyFactory` 负责根据登录类型创建对应的策略
|
||
|
||
**优势**:
|
||
- 支持多种登录方式,易于扩展新的登录方式
|
||
- 每种登录方式独立实现,互不影响
|
||
- 符合开闭原则(对扩展开放,对修改关闭)
|
||
|
||
### 2. 工厂模式(Factory Pattern)
|
||
|
||
**应用场景**:连接工厂
|
||
|
||
**实现方式**:
|
||
- `ISalesforceConnectionFactory<T>` 接口定义连接工厂的通用方法
|
||
- `AbstractConnectionFactory<T>` 抽象类提供连接缓存和管理逻辑
|
||
- 具体的连接工厂(如 `PartnerConnectionFactory`)继承 `AbstractConnectionFactory` 并实现 `createConnection` 方法
|
||
|
||
**优势**:
|
||
- 统一的连接创建和管理接口
|
||
- 支持连接缓存,提高性能
|
||
- 自动 Session 有效性检查
|
||
- 线程安全的连接获取
|
||
- 易于扩展新的连接类型
|
||
|
||
### 3. 模板方法模式(Template Method Pattern)
|
||
|
||
**应用场景**:连接工厂抽象基类
|
||
|
||
**实现方式**:
|
||
- `AbstractConnectionFactory<T>` 定义连接获取的模板方法
|
||
- `getConnection` 方法定义连接获取的流程(检查缓存、检查 Session 有效性、创建连接)
|
||
- `createConnection` 抽象方法由子类实现具体的连接创建逻辑
|
||
|
||
**优势**:
|
||
- 定义算法骨架,子类实现具体步骤
|
||
- 复用公共逻辑(缓存、Session 检查)
|
||
- 子类只需关注自己的实现细节
|
||
|
||
## 安全特性
|
||
|
||
### 1. 密码加密
|
||
- 使用 BCrypt 哈希算法加密存储密码
|
||
- 密码无法直接解密,只能验证
|
||
|
||
### 2. 敏感信息脱敏
|
||
- Session ID 在日志中会被脱敏处理
|
||
- 不会记录完整的 Session ID
|
||
|
||
### 3. 请求频率限制
|
||
- 登录接口有请求频率限制
|
||
- 每分钟最多 5 次登录尝试
|
||
|
||
### 4. XML 转义
|
||
- 使用 Apache Commons Text 的 `StringEscapeUtils.escapeXml11()` 进行 XML 转义
|
||
- 防止 XML 注入攻击
|
||
|
||
### 5. 连接超时处理
|
||
- 连接超时时间:10 秒
|
||
- 读取超时时间:30 秒
|
||
|
||
## 配置说明
|
||
|
||
### 环境配置
|
||
|
||
配置存储在 Redis 缓存中,通过 `SalesforceConfigCacheManager` 管理。
|
||
|
||
**主要配置项**:
|
||
|
||
| 配置项 | 说明 | 默认值 |
|
||
|--------|------|--------|
|
||
| salesforce.api.version | API 版本 | 65.0 |
|
||
| salesforce.environment.type | 环境类型(production/sandbox/custom) | production |
|
||
| salesforce.api.namespace | API 命名空间 | urn:partner.soap.sforce.com |
|
||
| salesforce.api.endpoint.production | 生产环境端点 | https://login.salesforce.com |
|
||
| salesforce.api.endpoint.sandbox | 沙盒环境端点 | https://test.salesforce.com |
|
||
| salesforce.api.endpoint.custom | 自定义环境端点 | - |
|
||
|
||
## 使用示例
|
||
|
||
### 示例 1:使用 SessionManager 获取会话信息
|
||
|
||
```java
|
||
@Autowired
|
||
private SessionManager sessionManager;
|
||
|
||
public void example() {
|
||
// 获取当前会话信息
|
||
SalesforceLoginResult result = sessionManager.getCurrentLoginResult("source");
|
||
|
||
if (result.isSuccess()) {
|
||
String sessionId = result.getSessionId();
|
||
String instanceUrl = result.getInstanceUrl();
|
||
System.out.println("Session ID: " + sessionId);
|
||
System.out.println("Instance URL: " + instanceUrl);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 示例 2:实现 PartnerConnectionFactory
|
||
|
||
```java
|
||
@Component
|
||
public class PartnerConnectionFactory extends AbstractConnectionFactory<PartnerConnection> {
|
||
|
||
@Override
|
||
protected PartnerConnection createConnection(String orgType) {
|
||
try {
|
||
// 获取 Session ID 和 Instance URL
|
||
String sessionId = sessionManager.getCurrentSession(orgType);
|
||
String instanceUrl = sessionManager.getInstanceUrl(orgType);
|
||
|
||
// 创建 ConnectorConfig
|
||
ConnectorConfig config = new ConnectorConfig();
|
||
config.setSessionId(sessionId);
|
||
config.setRestEndpoint(instanceUrl);
|
||
|
||
// 创建 PartnerConnection
|
||
return new PartnerConnection(config);
|
||
} catch (ConnectionException e) {
|
||
throw new RuntimeException("创建 PartnerConnection 失败", e);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 示例 3:使用连接工厂获取连接
|
||
|
||
```java
|
||
@Autowired
|
||
private PartnerConnectionFactory partnerConnectionFactory;
|
||
|
||
public void example() {
|
||
// 获取 PartnerConnection(自动处理缓存和 Session 有效性检查)
|
||
PartnerConnection connection = partnerConnectionFactory.getConnection("source");
|
||
|
||
// 使用连接执行操作
|
||
try {
|
||
QueryResult result = connection.query("SELECT Id, Name FROM Account LIMIT 10");
|
||
// 处理结果
|
||
} catch (ConnectionException e) {
|
||
// 处理异常
|
||
}
|
||
}
|
||
```
|
||
|
||
## 最佳实践
|
||
|
||
### 1. 使用 SessionManager 管理会话
|
||
- 始终通过 SessionManager 获取会话信息
|
||
- 不要直接使用缓存的 Session ID
|
||
- SessionManager 会自动处理 Session 过期和重新登录
|
||
|
||
### 2. 使用连接工厂获取连接
|
||
- 始终通过连接工厂获取连接
|
||
- 不要手动创建和管理连接
|
||
- 连接工厂会自动处理连接缓存和 Session 有效性检查
|
||
|
||
### 3. 处理异常
|
||
- 捕获并处理 ConnectionException
|
||
- 捕获并处理 ApiFault
|
||
- 使用 datai-salesforce-common 模块中的异常类
|
||
- 返回友好的错误消息
|
||
|
||
### 4. 日志记录
|
||
- 记录关键操作(登录、登出、获取会话等)
|
||
- 敏感信息(如 Session ID)需要脱敏处理
|
||
- 使用合适的日志级别(INFO、WARN、ERROR)
|
||
|
||
### 5. 性能优化
|
||
- 使用连接缓存,避免重复创建连接
|
||
- 使用 Redis 缓存配置信息
|
||
- 合理设置连接超时时间
|
||
|
||
## 常见问题
|
||
|
||
### Q1:Session 过期后如何处理?
|
||
A:SessionManager 会自动检测 Session 过期,并自动调用 autoLogin 方法重新登录。开发者无需手动处理。
|
||
|
||
### Q2:如何支持新的登录方式?
|
||
A:实现 LoginStrategy 接口,创建新的登录策略类,并使用 @Component 注解。LoginStrategyFactory 会自动发现并注册新的策略。
|
||
|
||
### Q3:如何清除缓存的连接?
|
||
A:调用连接工厂的 clearConnection 方法,传入 orgType 参数即可清除对应类型的连接缓存。
|
||
|
||
### Q4:如何区分 source 和 target ORG?
|
||
A:通过 orgType 参数区分,"source" 表示源 ORG,"target" 表示目标 ORG。SessionManager 和连接工厂都支持 orgType 参数。
|
||
|
||
### Q5:密码如何加密存储?
|
||
A:使用 BCrypt 哈希算法加密存储密码。密码无法直接解密,只能通过验证方式确认密码正确性。
|
||
|
||
## 总结
|
||
|
||
datai-salesforce-auth 模块是整个 Salesforce 集成体系的基础,提供了统一的认证和会话管理能力。通过策略模式支持多种登录方式,通过工厂模式提供统一的连接管理接口,具有良好的扩展性和可维护性。
|
||
|
||
**核心优势**:
|
||
1. 统一的认证和会话管理
|
||
2. 支持多种登录方式
|
||
3. 自动 Session 有效性检查
|
||
4. 连接缓存和线程安全
|
||
5. 良好的扩展性
|
||
6. 完善的安全特性
|
||
|
||
**适用场景**:
|
||
- 需要与 Salesforce 集成的应用
|
||
- 需要多种登录方式支持
|
||
- 需要统一的会话管理
|
||
- 需要高性能的连接管理
|