14

目前,我正在向我的请求添加一个授权标头,如下所示:

文件:SomeFile.cs

public interface ITestApi
{
    [Get("/api/test/{id}")]
    Task<string> GetTest([Header("Authorization")] string authorization, int id);

    [Get("/api/tests/")]
    Task<string> GetTests([Header("Authorization")] string authorization);
}

文件:SomeOtherFile.cs

var username = "xxx";
var password = "yyy";
var authHeader = "Basic " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
var baseAddress = "https://my.test.net";
ITestApi myApi = RestService.For<ITestApi>(baseAddress);

int id = 123;
var test= myApi.GetTest(authHeader, id);

var tests = myApi.GetTests(authHeader);

有没有办法全局设置 authHeader,这样我就不必将它作为参数传递给每个调用?(我使用的是改装版本 4.6.48)。换句话说,我希望能够进行这样的调用:

var test= myApi.GetTest(id);

var tests = myApi.GetTests();
4

3 回答 3

17

我找到了一个解决方案:

[Headers("Authorization: Basic")]
public interface ITestApi
{
    [Get("/api/test/{id}")]
    Task<string> GetTest(int id);

    [Get("/api/tests/")]
    Task<string> GetTests();
}


var username = "xxx";
var password = "yyy";
var authHeader = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
var baseAddress = "https://my.test.net";

var refitSettings = new RefitSettings()
{
    AuthorizationHeaderValueGetter = () => Task.FromResult(authHeader)
};

ITestApi myApi = RestService.For<ITestApi>(baseAddress, refitSettings);

int id = 123;
var test= myApi.GetTest(id);

var tests = myApi.GetTests();
于 2018-10-19T11:44:38.517 回答
6

thd 的答案对我不起作用,因为 Refit 目前只是 忽略 AuthorizationHeaderValueGetter并且请求不包含身份验证标头。

HttpClient我可以通过为我提供默认身份验证标头来使其工作:

string token = await GetTokenAsync().ConfigureAwait(false);
string endpointUrl = Environment.GetEnvironmentVariable(endpointVariable) ??
                     defaultEndpointUrl ?? DefaultEndpointUrl;

var client = new HttpClient(new HttpClientHandler())
{
    BaseAddress = new Uri(endpointUrl)
};
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

//TODO: remove as this is ignored anyway
//var refitSettings = new RefitSettings
//{
//    AuthorizationHeaderValueGetter = () => Task.FromResult($"{token}")
//};

var builder = RequestBuilder.ForType<TApiClient>();
return RestService.For(client, builder);

GetTokenAsync 如下所示:

public static async Task<string> GetAccessTokenAsync()
{
    // theoretically the token could have expired during the tests, but there is very low chance
    // so returning the same token if one was generated
    lock (SyncLock)
    {
        if (!string.IsNullOrWhiteSpace(Token))
            return Token;
    }

    var client = new HttpClient();
    var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
    {
        Address = $"{IdentityServerUrl}/connect/token",
        ClientId = "MY_CLIENT_APITEST",
        ClientSecret = IdentityServerPass,
        Scope = "api.read"

    }).ConfigureAwait(false);
    tokenResponse.HttpResponse.EnsureSuccessStatusCode();

    lock (SyncLock)
    {
        Token = tokenResponse.AccessToken;
        return Token;
    }
}
于 2020-05-02T09:22:06.573 回答
4

改装改变了它的方法。现在它使用默认的 .NET HttpHandler

var handler = new AuthHandler(credentials.Username, credentials.Password);
var githubApi = RestService.For<IGithubApi>(new HttpClient(handler)
                {
                    BaseAddress = new Uri("https://api.github.com")
                });


public class AuthHandler : HttpClientHandler
{
    private readonly string _username;
    private readonly string _password;

    public AuthHandler(string username, 
        string password)
    {
        _username = username;
        _password = password;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 
        CancellationToken cancellationToken)
    {
        request.Headers.Add("User-Agent", "<your user name or app name>");
        request.Headers.Authorization = new AuthenticationHeaderValue("Basic",
            Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(
                $"{_username}:{_password}")));

        return await base.SendAsync(request, cancellationToken)
            .ConfigureAwait(false);
    }
}
于 2020-12-26T22:45:34.113 回答