如何 Post 进入第三方 URL 并获得访问令牌

How to Post into a third party URL and get access token

在我的 ASP.NET Core-6 Web API 中,我遇到了挑战。我有一个第 3 方 URL,如下所示:

URL: http://api.thirdpartycompany.com:2233/api/oauth/login

Request:
{
 "username": to_be_shared,
 "password": to_be_shared
 
}
Response:
‘{
 "response_code": "00",
 "response_description": "Success"
 "data": {...},
 "size": 0,
 "access_token": "access_token",
 "refresh_token": "refresh_token",
 "expires_in": "18000000",
 "token_type": "BEARER"
}’

示例访问令牌请求调用:

url = "http://api.thirdpartycompany.com:2233/api/oauth/login"
payload = '{
 "username": to_be_shared,
 "password": to_be_shared
 
}'
headers = {
 'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data = payload)

我要 POST 进入第三方给定的 url 并得到他们的回应,包括访问令牌。

到目前为止,我已经这样做了:

DTO:

public class OAuthLoginRequest
{
    public string username { get; set; }
    public string password { get; set; }

}

public class OAuthLoginResponse
{
    public string response_code { get; set; }
    public string response_description { get; set; }
    public int size { get; set; }
    public string access_token { get; set; }
    public string refresh_token { get; set; }
    public string expires_in { get; set; }
    public string token_type { get; set; }
}

到目前为止,这是我所拥有的:

public class GenericResponseDto<T>
{
    public string response_code { get; set; }
    public string response_description { get; set; }
}

public interface IAuthService
{
    Task<GenericResponseDto<object>> LoginUser(OAuthLoginRequest request);
}


public class AuthService : IAuthService
{
    public async Task<GenericResponseDto<object>> LoginUser(OAuthLoginRequest request)
    {
        var response = new GenericResponseDto<object>();

        return response;
    }
}

DI服务扩展:

public static class DIServiceExtension
{   
    public static void AddDependencyInjection(this IServiceCollection services)
    {
        // Add Service Injections Here -- Auth
        services.AddScoped<IAuthService, AuthService>();
    }
}

Program.cs

builder.Services.AddDependencyInjection();

使用 HttpClient,如何完成 AuthService,当用户输入所需的用户名和密码时,提交请求然后它从第三方获得包含访问令牌的响应 URL (http://api.thirdpartycompany.com:2233/api/oauth/login)作为回应?

我该如何实现?

FWIW 请根据您使用的序列化/反序列化库使用 JsonPropertyNameAttribute or JsonProperty,并在 C# 类 类 C# 中保留属性名称(即 PascalCase,而不是 snake_case)
答案是假设你这样做了,所以我将使用 ResponseCode 属性 而不是 response_code


现在进入实际答案。

这个比较简单,你只需要post你的数据到第三部分API,读取结果,然后return把它放到调用堆栈上。像这样

public class AuthService : IAuthService
{
    // Configure your HttpClient injection as described here:
    // https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
    private readonly HttpClient _httpClient;

    public AuthService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<OAuthLoginResponse> LoginUser(OAuthLoginRequest request)
    {
        var postContent = new StringContent(
            JsonSerializer.Serialize(request),
            Encoding.UTF8,
            "application/json"
        );

        var response = await _httpClient.PostAsync("oauth/login", postContent);
        if (!response.IsSuccessStatusCode)
            throw new Exception("Third party API request failed");

        await using var stream = await response.Content.ReadAsStreamAsync();
        return JsonSerializer.DeserializeAsync<OAuthLoginResponse>(stream);
    }
}

您可以先将 GenericResponseDto 更改为 OAuthResponseDto 之类的特定内容,而不是直接 returning a OAuthLoginResponse,然后再更改您需要的字段,喜欢

public class OAuthResponseDto
{
    [JsonPropertyName("response_code")]
    public string ResponseCode { get; set; }

    [JsonPropertyName("response_description")]
    public string ResponseDescription { get; set; }

    // More properties, like AccessToken, RefreshToken, ExpiresIn...
}

然后将 LoginUser 的最后两行替换为:

await using var stream = await response.Content.ReadAsStreamAsync();
var response = JsonSerializer.DeserializeAsync<OAuthLoginResponse>(stream);

return new OAuthResponseDto
{
    ResponseCode = response.ResponseCode,
    ResponseDescription = response.ResponseDescription,
    // rest of the mapping
};

除此之外,这就是您配置 HttpClient 注入的方式

services.AddHttpClient<IAuthService, AuthService>(client =>
{
    client.BaseAddress = new Uri("http://api.thirdpartycompany.com:2233/api");
});

注意:我故意省略了很多错误检查以使这个答案简短而有趣,但它仍然是一个很长的答案,你必须添加在您的实施中进行错误检查。

注2:我也不能100%保证所有这些编译先走,我已经尽力了,但是我在Stack中写了很大一部分溢出编辑器,某处可能缺少括号或逗号或分号,琐碎的修复