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

Blazor中基于RestSharp实现OAuth2:登录跳转及授权后API调用问题

解决Blazor中Infusionsoft OAuth2授权及API调用问题

嘿,我来帮你梳理下当前的问题——你的代码逻辑有个关键误区:OAuth2授权码流程的第一步是引导用户在浏览器里访问授权页面,而不是用RestSharp发送POST请求。RestSharp适合后续的令牌交换和API调用,而非初始化授权跳转。

1. 修正授权跳转逻辑

在Blazor里,你需要借助NavigationManager实现页面重定向,引导用户到Infusionsoft的授权页。具体步骤如下:

  • 注入NavigationManager服务
  • 构造包含所有必填参数的授权URL
  • 调用NavigateTo方法完成跳转

示例代码:

@page "/infusionsoft"
@inject NavigationManager NavManager
@using System.Web;

<button @onclick="RedirectToInfusionsoftAuth">授权登录Infusionsoft</button>

@code {
    private void RedirectToInfusionsoftAuth()
    {
        var clientId = "myid";
        var redirectUri = "https://your-blazor-app.com/infusionsoft-callback"; // 替换成你在Infusionsoft后台配置的回调地址
        var scope = "full"; // 根据业务需求调整权限范围
        var state = Guid.NewGuid().ToString(); // 用于防CSRF攻击,建议存到LocalStorage或Session

        // 构造符合OAuth2规范的授权URL
        var authUrl = $"https://signin.infusionsoft.com/app/oauth/authorize?client_id={HttpUtility.UrlEncode(clientId)}" +
                      $"&redirect_uri={HttpUtility.UrlEncode(redirectUri)}" +
                      $"&response_type=code" +
                      $"&scope={HttpUtility.UrlEncode(scope)}" +
                      $"&state={HttpUtility.UrlEncode(state)}";

        // 强制跳转授权页面
        NavManager.NavigateTo(authUrl, forceLoad: true);
    }
}

2. 回调页面交换访问令牌

用户授权成功后,Infusionsoft会重定向到你配置的redirect_uri,并携带code(授权码)和state参数。此时你需要在回调页面(比如/infusionsoft-callback)用授权码交换访问令牌,这才是RestSharp的适用场景:

@page "/infusionsoft-callback"
@inject NavigationManager NavManager
@using RestSharp;
@using Newtonsoft.Json;

@code {
    protected override async Task OnInitializedAsync()
    {
        // 从URL中提取授权码和state参数
        var uri = new Uri(NavManager.Uri);
        var code = HttpUtility.ParseQueryString(uri.Query).Get("code");
        var state = HttpUtility.ParseQueryString(uri.Query).Get("state");

        // 验证state(和之前存储的对比,防止CSRF攻击)
        // 示例省略state验证逻辑,实际开发中必须添加

        if (!string.IsNullOrEmpty(code))
        {
            var tokenUrl = "https://api.infusionsoft.com/token";
            var clientId = "myid";
            var clientSecret = "mysecret";
            var redirectUri = "https://your-blazor-app.com/infusionsoft-callback"; // 必须和授权跳转时的地址一致

            var restClient = new RestClient(tokenUrl);
            var request = new RestRequest(Method.Post);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddParameter("client_id", clientId);
            request.AddParameter("client_secret", clientSecret);
            request.AddParameter("grant_type", "authorization_code");
            request.AddParameter("code", code);
            request.AddParameter("redirect_uri", redirectUri);

            var response = await restClient.ExecuteAsync(request);
            if (response.IsSuccessful)
            {
                // 解析令牌响应
                var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(response.Content);
                
                // 安全存储令牌(Blazor WebAssembly用LocalStorage,Server用Session)
                // 示例:await localStorage.SetItemAsync("access_token", tokenResponse.AccessToken);
                
                // 跳转至API调用页面
                NavManager.NavigateTo("/infusionsoft-api");
            }
            else
            {
                Console.WriteLine($"令牌交换失败:{response.Content}");
            }
        }
    }

    // 定义令牌响应模型
    public class TokenResponse
    {
        [JsonProperty("access_token")]
        public string AccessToken { get; set; }
        
        [JsonProperty("token_type")]
        public string TokenType { get; set; }
        
        [JsonProperty("expires_in")]
        public int ExpiresIn { get; set; }
        
        [JsonProperty("refresh_token")]
        public string RefreshToken { get; set; }
    }
}

3. 授权后调用Infusionsoft API

拿到访问令牌后,只需在请求头中添加Bearer令牌,即可用RestSharp调用Infusionsoft的API:

@page "/infusionsoft-api"
@inject ILocalStorageService localStorage // 假设使用Blazored.LocalStorage存储令牌
@using RestSharp;

<button @onclick="CallInfusionsoftApi">调用联系人API</button>
<p>API响应:@apiResponse</p>

@code {
    private string apiResponse;

    private async Task CallInfusionsoftApi()
    {
        var accessToken = await localStorage.GetItemAsync<string>("access_token");
        if (string.IsNullOrEmpty(accessToken))
        {
            apiResponse = "未找到有效令牌,请先完成授权";
            return;
        }

        var apiUrl = "https://api.infusionsoft.com/crm/rest/v1/contacts"; // 示例API端点
        var restClient = new RestClient(apiUrl);
        var request = new RestRequest(Method.Get);
        
        // 添加Bearer授权头
        request.AddHeader("Authorization", $"Bearer {accessToken}");
        request.AddHeader("Accept", "application/json");

        var response = await restClient.ExecuteAsync(request);
        if (response.IsSuccessful)
        {
            apiResponse = response.Content;
        }
        else
        {
            apiResponse = $"API调用失败:{response.StatusCode} - {response.Content}";
        }
    }
}

关键注意事项

  • 确保在Infusionsoft开发者平台中配置的redirect_uri和代码中的完全一致
  • 必须验证state参数,防范跨站请求伪造攻击
  • 令牌需安全存储,Blazor WebAssembly中使用LocalStorage时注意敏感数据风险
  • 记得处理令牌过期场景,用refresh_token刷新访问令牌

内容的提问来源于stack exchange,提问作者Mark Daniel Louwe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 11:47:55