You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MVC应用调用DocuSign API重复认证问题咨询

嘿,这个问题我太熟悉了!你现在遇到的每次重启都要重新授权的问题,核心原因是没把第一次授权后拿到的关键凭据存下来,而且当前用的授权码流程本身需要用户手动触发一次,但我们可以通过两种方式实现「一次性完成认证」的效果,不用每次重启都折腾:

方案一:优化现有授权码流程,持久化认证凭据

授权码流程本身需要用户首次手动授权,但我们可以把授权后拿到的令牌、账户信息持久化起来,后续重启直接复用,不用再走授权流程:

  • 当你第一次通过授权码拿到 access_token、refresh_token、账户ID和Base URL后,把这些信息(尤其是refresh_token、账户ID、Base URL)加密存储到安全的地方,比如数据库、加密配置文件或者分布式缓存
  • 应用重启时,先检查有没有保存的凭据:
    • 如果有,直接用refresh_token去获取新的access_token,完全不需要用户介入
    • 只有当refresh_token过期(有效期30天)时,才需要重新引导用户授权一次

给你调整后的代码示例:

public ActionResult Index()
{
    // 从持久化存储读取已保存的信息(这里需要你实现自己的存储逻辑)
    var savedAccountId = GetSavedAccountId();
    var savedBaseUrl = GetSavedBaseUrl();
    var savedRefreshToken = GetSavedRefreshToken();

    if (!string.IsNullOrEmpty(savedAccountId) && !string.IsNullOrEmpty(savedBaseUrl) && !string.IsNullOrEmpty(savedRefreshToken))
    {
        // 用refresh_token获取新的access_token
        ApiClient apiClient = new ApiClient(savedBaseUrl);
        var tokenResponse = apiClient.GenerateAccessToken(IntegratorKey, savedRefreshToken);
        
        // 更新存储里的access_token和过期时间
        SaveAccessToken(tokenResponse.AccessToken, tokenResponse.ExpiresIn);
        
        // 直接配置API客户端,跳转到业务页面
        DocuSign.eSign.Client.Configuration.Default.ApiClient = apiClient;
        DocuSign.eSign.Client.Configuration.Default.AddDefaultHeader("Authorization", "Bearer " + tokenResponse.AccessToken);
        
        return RedirectToAction("Dashboard");
    }
    else
    {
        // 没有保存的凭据,走首次授权流程
        ApiClient apiClient = new ApiClient(RestApiUrl);
        var authUrl = apiClient.GetAuthorizationUri(IntegratorKey, RedirectUri, DocuSign.eSign.Client.OAuth.CODE);
        return Redirect(authUrl.ToString());
    }
}

// 授权回调方法,处理授权码并保存凭据
public ActionResult Callback(string code)
{
    ApiClient apiClient = new ApiClient(RestApiUrl);
    var tokenResponse = apiClient.GenerateAccessToken(IntegratorKey, RedirectUri, code);
    
    // 获取账户ID和Base URL
    var accountInfo = apiClient.GetUserInfo(tokenResponse.AccessToken);
    var accountId = accountInfo.Accounts.First().AccountId;
    var baseUrl = accountInfo.Accounts.First().BaseUri + "/restapi";
    
    // 加密持久化这些敏感信息!
    SaveAccountId(accountId);
    SaveBaseUrl(baseUrl);
    SaveRefreshToken(tokenResponse.RefreshToken);
    SaveAccessToken(tokenResponse.AccessToken, tokenResponse.ExpiresIn);
    
    // 配置API客户端
    DocuSign.eSign.Client.Configuration.Default.ApiClient = apiClient;
    DocuSign.eSign.Client.Configuration.Default.AddDefaultHeader("Authorization", "Bearer " + tokenResponse.AccessToken);
    
    return RedirectToAction("Dashboard");
}
方案二:改用JWT认证流程(更适合无人值守的后台应用)

如果你的应用是服务端后台运行、不需要每个用户单独授权,JWT流程是更好的选择——只需要用户一次性同意应用权限,之后应用可以在后台自动获取令牌,完全不需要用户介入:

  1. 先在DocuSign开发者控制台创建JWT类型的应用,下载RSA密钥对(.pem格式的私钥文件)
  2. 让测试用户(沙箱环境的账户)一次性授权你的应用,或者用控制台的「模拟授权」功能获取用户的userId
  3. 应用启动时,直接用JWT生成令牌,同时获取账户ID和Base URL,缓存这些信息即可

代码示例如下:

public ActionResult Index()
{
    // 先检查缓存里的有效凭据
    var cachedAccountId = GetCachedAccountId();
    var cachedBaseUrl = GetCachedBaseUrl();
    var cachedAccessToken = GetCachedAccessToken();
    
    if (!string.IsNullOrEmpty(cachedAccountId) && !string.IsNullOrEmpty(cachedBaseUrl) && !string.IsNullOrEmpty(cachedAccessToken))
    {
        // 直接复用缓存的信息
        ApiClient apiClient = new ApiClient(cachedBaseUrl);
        DocuSign.eSign.Client.Configuration.Default.ApiClient = apiClient;
        DocuSign.eSign.Client.Configuration.Default.AddDefaultHeader("Authorization", "Bearer " + cachedAccessToken);
        return RedirectToAction("Dashboard");
    }
    
    // 缓存无效,用JWT获取新的令牌和账户信息
    ApiClient apiClient = new ApiClient(RestApiUrl);
    // 读取本地的RSA私钥文件
    var rsaPrivateKey = File.ReadAllText(@"path/to/your/private.key");
    // 生成JWT令牌,有效期1小时
    var tokenResponse = apiClient.RequestJWTUserToken(IntegratorKey, UserId, "account-d.docusign.com", rsaPrivateKey, 3600);
    
    // 获取账户ID和Base URL
    var accountInfo = apiClient.GetUserInfo(tokenResponse.AccessToken);
    var accountId = accountInfo.Accounts.First().AccountId;
    var baseUrl = accountInfo.Accounts.First().BaseUri + "/restapi";
    
    // 缓存这些信息(和access_token有效期一致,1小时)
    CacheAccountId(accountId, 3600);
    CacheBaseUrl(baseUrl, 3600);
    CacheAccessToken(tokenResponse.AccessToken, 3600);
    
    // 配置API客户端
    DocuSign.eSign.Client.Configuration.Default.ApiClient = apiClient;
    DocuSign.eSign.Client.Configuration.Default.AddDefaultHeader("Authorization", "Bearer " + tokenResponse.AccessToken);
    
    return RedirectToAction("Dashboard");
}

关键注意事项

  • 不管用哪种方案,敏感数据(refresh_token、RSA私钥、access_token)一定要加密存储,绝对不能明文暴露
  • 沙箱环境的认证逻辑和生产环境完全一致,这些方案可以直接迁移到生产
  • 如果是多用户场景(每个用户用自己的DocuSign账户),优先选授权码+持久化refresh_token;如果是单账户统一处理业务,JWT流程更省心

内容的提问来源于stack exchange,提问作者Vinit Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:30:30