506 lines
12 KiB
Markdown
506 lines
12 KiB
Markdown
|
|
# SalesforceLoginController 方法调用说明文档
|
|||
|
|
|
|||
|
|
## 1. 概述
|
|||
|
|
|
|||
|
|
SalesforceLoginController提供了一套完整的Salesforce登录相关API,支持多种登录方式,包括用户名密码登录、JWT登录、客户端凭证登录和OAuth登录。
|
|||
|
|
|
|||
|
|
## 2. API基础信息
|
|||
|
|
|
|||
|
|
- 基础URL: `/salesforce/login`
|
|||
|
|
- 请求格式: JSON (POST请求)
|
|||
|
|
- 响应格式: JSON
|
|||
|
|
- 统一响应格式:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200, // 响应状态码
|
|||
|
|
"msg": "Success", // 响应消息
|
|||
|
|
"data": {} // 响应数据
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 3. 详细方法说明
|
|||
|
|
|
|||
|
|
### 3.1 登录Salesforce
|
|||
|
|
|
|||
|
|
**方法名称**: `login`
|
|||
|
|
|
|||
|
|
**HTTP请求**: `POST /salesforce/login/login`
|
|||
|
|
|
|||
|
|
**功能说明**: 支持多种登录方式,根据loginType动态选择
|
|||
|
|
|
|||
|
|
**请求参数**:
|
|||
|
|
|
|||
|
|
| 参数名 | 类型 | 必须 | 说明 | 示例值 |
|
|||
|
|
|--------|------|------|------|--------|
|
|||
|
|
| loginType | String | 是 | 登录类型,可选值:password, jwt, client_credentials, oauth | "password" |
|
|||
|
|
| username | String | 否 | 用户名,password和jwt登录方式必填 | "user@example.com" |
|
|||
|
|
| password | String | 否 | 密码,password登录方式必填 | "password123" |
|
|||
|
|
| securityToken | String | 否 | 安全令牌,password登录方式可选 | "SECURITY_TOKEN" |
|
|||
|
|
| clientId | String | 否 | 客户端ID,jwt和client_credentials登录方式必填 | "CLIENT_ID" |
|
|||
|
|
| clientSecret | String | 否 | 客户端密钥,client_credentials登录方式必填 | "CLIENT_SECRET" |
|
|||
|
|
| jwtToken | String | 否 | JWT令牌,jwt登录方式可选 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." |
|
|||
|
|
| privateKeyPath | String | 否 | 私钥路径,jwt登录方式可选 | "/path/to/private.key" |
|
|||
|
|
| privateKeyPassword | String | 否 | 私钥密码,jwt登录方式可选 | "KEY_PASSWORD" |
|
|||
|
|
| environment | String | 否 | 环境类型,可选值:production, sandbox, custom,默认production | "production" |
|
|||
|
|
| customDomain | String | 否 | 自定义域名,environment为custom时必填 | "custom.salesforce.com" |
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "Login successful",
|
|||
|
|
"data": {
|
|||
|
|
"accessToken": "00D5f0000000001!AQwAQG...",
|
|||
|
|
"instanceUrl": "https://na152.salesforce.com",
|
|||
|
|
"idToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|||
|
|
"refreshToken": "5Aep861q6x...",
|
|||
|
|
"expiresAt": "2025-12-10T12:00:00",
|
|||
|
|
"success": true,
|
|||
|
|
"loginType": "password",
|
|||
|
|
"username": "user@example.com"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**调用示例**:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 用户名密码登录
|
|||
|
|
fetch('/salesforce/login/login', {
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
},
|
|||
|
|
body: JSON.stringify({
|
|||
|
|
loginType: 'password',
|
|||
|
|
username: 'user@example.com',
|
|||
|
|
password: 'password123',
|
|||
|
|
environment: 'production'
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => console.log(data));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 刷新访问令牌
|
|||
|
|
|
|||
|
|
**方法名称**: `refreshToken`
|
|||
|
|
|
|||
|
|
**HTTP请求**: `POST /salesforce/login/refresh-token`
|
|||
|
|
|
|||
|
|
**功能说明**: 根据登录类型刷新访问令牌
|
|||
|
|
|
|||
|
|
**请求参数**:
|
|||
|
|
|
|||
|
|
| 参数名 | 类型 | 必须 | 说明 | 示例值 |
|
|||
|
|
|--------|------|------|------|--------|
|
|||
|
|
| refreshToken | String | 是 | 刷新令牌 | "5Aep861q6x..." |
|
|||
|
|
| loginType | String | 是 | 登录类型 | "password" |
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "Token refreshed successfully",
|
|||
|
|
"data": {
|
|||
|
|
"accessToken": "00D5f0000000001!AQwAQG...",
|
|||
|
|
"instanceUrl": "https://na152.salesforce.com",
|
|||
|
|
"expiresAt": "2025-12-10T12:00:00",
|
|||
|
|
"success": true,
|
|||
|
|
"loginType": "password"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**调用示例**:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
fetch('/salesforce/login/refresh-token?refreshToken=5Aep861q6x...&loginType=password', {
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => console.log(data));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 登出Salesforce
|
|||
|
|
|
|||
|
|
**方法名称**: `logout`
|
|||
|
|
|
|||
|
|
**HTTP请求**: `POST /salesforce/login/logout`
|
|||
|
|
|
|||
|
|
**功能说明**: 登出并清除登录状态
|
|||
|
|
|
|||
|
|
**请求参数**:
|
|||
|
|
|
|||
|
|
| 参数名 | 类型 | 必须 | 说明 | 示例值 |
|
|||
|
|
|--------|------|------|------|--------|
|
|||
|
|
| accessToken | String | 是 | 访问令牌 | "00D5f0000000001!AQwAQG..." |
|
|||
|
|
| loginType | String | 是 | 登录类型 | "password" |
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "Logout successful",
|
|||
|
|
"data": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**调用示例**:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
fetch('/salesforce/login/logout?accessToken=00D5f0000000001!AQwAQG...&loginType=password', {
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => console.log(data));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.4 获取当前登录状态
|
|||
|
|
|
|||
|
|
**方法名称**: `getLoginStatus`
|
|||
|
|
|
|||
|
|
**HTTP请求**: `GET /salesforce/login/status`
|
|||
|
|
|
|||
|
|
**功能说明**: 获取当前的登录状态信息
|
|||
|
|
|
|||
|
|
**请求参数**: 无
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "Login status retrieved",
|
|||
|
|
"data": {
|
|||
|
|
"accessToken": "00D5f0000000001!AQwAQG...",
|
|||
|
|
"instanceUrl": "https://na152.salesforce.com",
|
|||
|
|
"loginType": "password",
|
|||
|
|
"username": "user@example.com",
|
|||
|
|
"success": true,
|
|||
|
|
"sessionValid": true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**调用示例**:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
fetch('/salesforce/login/status', {
|
|||
|
|
method: 'GET',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => console.log(data));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.5 清除登录状态
|
|||
|
|
|
|||
|
|
**方法名称**: `clearLoginStatus`
|
|||
|
|
|
|||
|
|
**HTTP请求**: `POST /salesforce/login/clear-status`
|
|||
|
|
|
|||
|
|
**功能说明**: 清除当前的登录状态信息
|
|||
|
|
|
|||
|
|
**请求参数**: 无
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "Login status cleared successfully",
|
|||
|
|
"data": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**调用示例**:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
fetch('/salesforce/login/clear-status', {
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => console.log(data));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.6 获取支持的登录类型
|
|||
|
|
|
|||
|
|
**方法名称**: `getSupportedLoginTypes`
|
|||
|
|
|
|||
|
|
**HTTP请求**: `GET /salesforce/login/supported-types`
|
|||
|
|
|
|||
|
|
**功能说明**: 获取系统支持的所有登录方式类型
|
|||
|
|
|
|||
|
|
**请求参数**: 无
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "Supported login types retrieved",
|
|||
|
|
"data": ["password", "jwt", "client_credentials", "oauth"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**调用示例**:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
fetch('/salesforce/login/supported-types', {
|
|||
|
|
method: 'GET',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => console.log(data));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.7 验证会话有效性
|
|||
|
|
|
|||
|
|
**方法名称**: `validateSession`
|
|||
|
|
|
|||
|
|
**HTTP请求**: `GET /salesforce/login/validate-session`
|
|||
|
|
|
|||
|
|
**功能说明**: 验证当前会话是否有效
|
|||
|
|
|
|||
|
|
**请求参数**: 无
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "Session is valid",
|
|||
|
|
"data": {
|
|||
|
|
"accessToken": "00D5f0000000001!AQwAQG...",
|
|||
|
|
"instanceUrl": "https://na152.salesforce.com",
|
|||
|
|
"loginType": "password",
|
|||
|
|
"username": "user@example.com",
|
|||
|
|
"success": true,
|
|||
|
|
"sessionValid": true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**调用示例**:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
fetch('/salesforce/login/validate-session', {
|
|||
|
|
method: 'GET',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => console.log(data));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 4. 前端调用最佳实践
|
|||
|
|
|
|||
|
|
### 4.1 登录流程
|
|||
|
|
|
|||
|
|
1. 获取支持的登录类型:`GET /salesforce/login/supported-types`
|
|||
|
|
2. 根据用户选择的登录方式,构建相应的登录请求
|
|||
|
|
3. 调用登录接口:`POST /salesforce/login/login`
|
|||
|
|
4. 保存登录结果中的accessToken和refreshToken
|
|||
|
|
5. 定期调用会话验证接口:`GET /salesforce/login/validate-session`
|
|||
|
|
6. 当token过期时,调用刷新token接口:`POST /salesforce/login/refresh-token`
|
|||
|
|
7. 用户登出时,调用登出接口:`POST /salesforce/login/logout`
|
|||
|
|
|
|||
|
|
### 4.2 错误处理
|
|||
|
|
|
|||
|
|
- 检查响应的code字段,非200表示错误
|
|||
|
|
- 处理常见错误:
|
|||
|
|
- 401 Unauthorized:登录信息无效
|
|||
|
|
- 403 Forbidden:权限不足
|
|||
|
|
- 500 Internal Server Error:服务器内部错误
|
|||
|
|
- 503 Service Unavailable:服务不可用
|
|||
|
|
|
|||
|
|
### 4.3 安全建议
|
|||
|
|
|
|||
|
|
- 敏感信息(如密码、token)不要明文存储在前端
|
|||
|
|
- 使用HTTPS协议传输所有请求
|
|||
|
|
- 定期更新token,避免token过期
|
|||
|
|
- 登出时确保清除所有本地存储的token信息
|
|||
|
|
|
|||
|
|
## 5. 示例代码
|
|||
|
|
|
|||
|
|
### 5.1 登录示例(Vue 3)
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<div>
|
|||
|
|
<h1>Salesforce Login</h1>
|
|||
|
|
<div>
|
|||
|
|
<label for="loginType">Login Type:</label>
|
|||
|
|
<select v-model="loginType">
|
|||
|
|
<option value="password">Password</option>
|
|||
|
|
<option value="jwt">JWT</option>
|
|||
|
|
<option value="client_credentials">Client Credentials</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div v-if="loginType === 'password'">
|
|||
|
|
<div>
|
|||
|
|
<label for="username">Username:</label>
|
|||
|
|
<input type="text" v-model="username" />
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<label for="password">Password:</label>
|
|||
|
|
<input type="password" v-model="password" />
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<button @click="login">Login</button>
|
|||
|
|
<div v-if="error" class="error">{{ error }}</div>
|
|||
|
|
<div v-if="success" class="success">{{ success }}</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { ref } from 'vue';
|
|||
|
|
|
|||
|
|
const loginType = ref('password');
|
|||
|
|
const username = ref('');
|
|||
|
|
const password = ref('');
|
|||
|
|
const error = ref('');
|
|||
|
|
const success = ref('');
|
|||
|
|
|
|||
|
|
const login = async () => {
|
|||
|
|
try {
|
|||
|
|
const response = await fetch('/salesforce/login/login', {
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
},
|
|||
|
|
body: JSON.stringify({
|
|||
|
|
loginType: loginType.value,
|
|||
|
|
username: username.value,
|
|||
|
|
password: password.value
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const data = await response.json();
|
|||
|
|
|
|||
|
|
if (data.code === 200) {
|
|||
|
|
success.value = 'Login successful';
|
|||
|
|
error.value = '';
|
|||
|
|
// 保存token等信息
|
|||
|
|
localStorage.setItem('salesforceAccessToken', data.data.accessToken);
|
|||
|
|
localStorage.setItem('salesforceRefreshToken', data.data.refreshToken);
|
|||
|
|
} else {
|
|||
|
|
error.value = data.msg;
|
|||
|
|
success.value = '';
|
|||
|
|
}
|
|||
|
|
} catch (err) {
|
|||
|
|
error.value = 'Login failed: ' + err.message;
|
|||
|
|
success.value = '';
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 会话验证示例(React)
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
import React, { useEffect, useState } from 'react';
|
|||
|
|
|
|||
|
|
const SessionValidator = () => {
|
|||
|
|
const [sessionValid, setSessionValid] = useState(false);
|
|||
|
|
const [loading, setLoading] = useState(true);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
const validateSession = async () => {
|
|||
|
|
try {
|
|||
|
|
const response = await fetch('/salesforce/login/validate-session', {
|
|||
|
|
method: 'GET',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const data = await response.json();
|
|||
|
|
setSessionValid(data.code === 200 && data.data.sessionValid);
|
|||
|
|
} catch (err) {
|
|||
|
|
setSessionValid(false);
|
|||
|
|
} finally {
|
|||
|
|
setLoading(false);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
validateSession();
|
|||
|
|
// 每5分钟验证一次会话
|
|||
|
|
const interval = setInterval(validateSession, 5 * 60 * 1000);
|
|||
|
|
|
|||
|
|
return () => clearInterval(interval);
|
|||
|
|
}, []);
|
|||
|
|
|
|||
|
|
if (loading) {
|
|||
|
|
return <div>Checking session...</div>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<h2>Session Status: {sessionValid ? 'Valid' : 'Invalid'}</h2>
|
|||
|
|
{!sessionValid && (
|
|||
|
|
<button onClick={() => window.location.href = '/login'}>
|
|||
|
|
Login Again
|
|||
|
|
</button>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default SessionValidator;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 6. 常见问题
|
|||
|
|
|
|||
|
|
### 6.1 如何选择合适的登录方式?
|
|||
|
|
|
|||
|
|
- **password登录**:适用于开发测试环境,需要用户名和密码
|
|||
|
|
- **jwt登录**:适用于机器到机器的集成,安全性较高
|
|||
|
|
- **client_credentials登录**:适用于服务器到服务器的集成
|
|||
|
|
- **oauth登录**:适用于第三方应用集成,支持授权码流程
|
|||
|
|
|
|||
|
|
### 6.2 token过期怎么办?
|
|||
|
|
|
|||
|
|
当token过期时,系统会自动检测并返回sessionValid: false,此时需要:
|
|||
|
|
1. 调用`POST /salesforce/login/refresh-token`接口刷新token
|
|||
|
|
2. 如果刷新失败,需要重新登录
|
|||
|
|
|
|||
|
|
### 6.3 如何获取当前登录用户信息?
|
|||
|
|
|
|||
|
|
调用`GET /salesforce/login/status`接口,响应中包含username和其他用户信息
|
|||
|
|
|
|||
|
|
### 6.4 如何处理不同环境?
|
|||
|
|
|
|||
|
|
通过environment参数指定环境类型:
|
|||
|
|
- production:生产环境
|
|||
|
|
- sandbox:沙盒环境
|
|||
|
|
- custom:自定义环境,需要同时提供customDomain参数
|
|||
|
|
|
|||
|
|
## 7. 版本说明
|
|||
|
|
|
|||
|
|
- 当前版本:1.0.0
|
|||
|
|
- 支持的Salesforce API版本:61.0.0
|
|||
|
|
|
|||
|
|
## 8. 联系方式
|
|||
|
|
|
|||
|
|
如有问题,请联系系统管理员或开发团队。
|