26 KiB
datai-salesforce-auth 模块详细文档
模块概述
基本信息
- 模块名称: datai-salesforce-auth
- 模块类型: 认证和会话管理模块
- 版本: 1.0.0
- Java 版本: 22
- 编码: UTF-8
功能描述
datai-salesforce-auth 模块负责 Salesforce 认证和会话管理,提供多种登录方式支持、会话信息缓存、连接工厂等核心功能。该模块是整个 Salesforce 集成体系的基础,为其他模块(Partner、Apex、Metadata、Tooling)提供统一的认证和会话管理能力。
核心特性
- 多种登录方式支持:OAuth2、Salesforce CLI、Legacy Credential、Session ID
- 会话管理:自动 Session 有效性检查、过期自动刷新
- 连接工厂:统一的连接创建和管理接口
- 登录历史:完整的登录历史记录和查询
- 安全特性:密码加密、敏感信息脱敏、请求频率限制
- 多 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 的获取,支持会话有效性检查和自动重新登录。
核心方法:
/**
* 获取当前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 连接工厂的统一接口,提供连接获取、清除缓存等功能。
核心方法:
/**
* 获取连接实例
* 如果缓存中没有有效的连接,则创建新的连接
*
* @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 方法。
核心方法:
/**
* 获取连接实例
* 自动处理连接缓存和 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
功能描述: 定义不同登录方式的通用方法,支持策略模式。
核心方法:
/**
* 执行登录操作
*
* @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
功能描述: 负责根据登录类型创建对应的登录策略,使用工厂模式。
核心方法:
/**
* 根据登录类型获取对应的登录策略
*
* @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 登录方式。
核心流程:
- 验证请求参数(用户名、密码)
- 获取 Salesforce 配置(API 版本、环境类型、端点 URL 等)
- 构建 SOAP 登录请求
- 发送 SOAP 请求到 Salesforce
- 解析 SOAP 响应,提取 Session ID 和 Instance URL
- 返回登录结果
特性:
- 使用 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 | 时区 |
核心方法:
/**
* 判断 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 登录操作,支持多种登录方式
请求参数:
{
"loginType": "legacy_credential",
"username": "user@example.com",
"password": "password",
"securityToken": "token",
"orgType": "source"
}
响应示例:
{
"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 信息
响应示例:
{
"code": 200,
"message": "登出成功",
"data": null
}
3. 获取登录历史
接口: GET /salesforce/login/history
功能: 查询登录历史记录
响应示例:
{
"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
功能: 查询当前登录会话信息
响应示例:
{
"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 依赖
<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 获取会话信息
@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
@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:使用连接工厂获取连接
@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 集成体系的基础,提供了统一的认证和会话管理能力。通过策略模式支持多种登录方式,通过工厂模式提供统一的连接管理接口,具有良好的扩展性和可维护性。
核心优势:
- 统一的认证和会话管理
- 支持多种登录方式
- 自动 Session 有效性检查
- 连接缓存和线程安全
- 良好的扩展性
- 完善的安全特性
适用场景:
- 需要与 Salesforce 集成的应用
- 需要多种登录方式支持
- 需要统一的会话管理
- 需要高性能的连接管理