繁体   English   中英

HttpClient System.Net.Http.HttpRequestException:响应状态码不表示成功:401(未授权)

[英]HttpClient System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized)

我正在尝试从我的 asp.net 核心应用程序向Auth0发送请求。 我为此使用HttpClient

问题是当我在 postman 中创建相同的请求时,一切正常,但是如果我从我的 .NET Core 应用程序中使用它,它就会抛出

System.Net.Http.HttpRequestException:响应状态码不表示成功:401(未授权)。

这是 postman 示例的图像:

在此处输入图像描述 有关任务的更多详细信息:

请求类型为POST

成功调用将返回access_token

POST 请求需要很少的正文参数:

  1. 授予类型
  2. client_id
  3. client_secret
  4. 观众

并且Header内容类型必须是application/x-www-form-urlencoded

因此来自 postman 的请求如下所示:

https://mydemoapplication.auth0.com/oauth/token grant_type=client_credentials &client_id=some_my_id &client_secret=some_my_client_secrets &audience=https://mydemoapplication.auth0.com/api/v2/

这工作得很好。

但是,当我尝试从.NET CORE Web api重复相同的操作时,我得到401 (Unauthorized). 每时每刻。

这是我的 C# 代码:

首先我们从RequestTokenFromAuth0方法开始

 public async Task<string> RequestTokenFromAuth0(CancellationToken cancellationToken)
 {
            // tokenUrl represents https://mydemoapplication.auth0.com/oauth/token
            var tokenUrl = $"{_auth0HttpConfig.TokenEndpoint}";

            // Creating anonymous object which will be used in post request
            var data = new
            {
                grant_type = "client_credentials",
                client_id =  _auth0HttpConfig.ClientId ,
                client_secret = _auth0HttpConfig.ClientSecret,
                audience = _auth0HttpConfig.Audience
            };

            //var data = $"grant_type=client_credentials&client_id={_auth0HttpConfig.ClientId}&client_secret={_auth0HttpConfig.ClientSecret}&audience={_auth0HttpConfig.Audience}";

            var response = await _auth0Client.PostToken<Auth0Auth>(tokenUrl, data, cancellationToken);
             
            if(response!= null && response.Success && response.Data != null && !string.IsNullOrWhiteSpace(response.Data.Token))
            {
                return response.Data.Token;
            }
            else
            {
                throw new ArgumentException("Token is not retrieved.");
            }
        }


public async Task<T> PostToken<T>(string endpoint, object jsonObject, CancellationToken cancellationToken)
{
    if (string.IsNullOrWhiteSpace(endpoint))
    {
        throw new ArgumentNullException(endpoint);
    }

    var reqMessage = GenerateTokenRequestMessage(HttpMethod.Post, jsonObject, endpoint);

    var result = await GetResult<T>(httpRequestMessage, cancellationToken);

    return result;
}


public HttpRequestMessage GenerateTokenRequestMessage(HttpMethod httpMethod, object objectToPost, string endpoint)
{ 
    var httpRequestMessage = new HttpRequestMessage(httpMethod, endpoint);

    var serializedObjectToCreate = JsonConvert.SerializeObject(objectToPost, new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Ignore
    });

    httpRequestMessage.Content = new StringContent(serializedObjectToCreate);
    httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

    return httpRequestMessage;
}

private async Task<T> GetResult<T>(HttpRequestMessage request, CancellationToken cancellationToken)
{
    try
    {
        HttpResponseMessage response = await _client.SendAsync(request, cancellationToken);

        response.EnsureSuccessStatusCode(); // THIS LINE Throws exception 401 Unathorized

        var result = await response.Content.ReadAsStringAsync();

        return JsonConvert.DeserializeObject<T>(result);
    }
    catch (Exception ex)
    {
        throw;
    }
}

这里出了点问题,我不知道为什么我没有得到授权,这里可能有什么问题我不确定! 任何形式的帮助都会很棒!

PS 从 postman 再次重复,一切正常!

谢谢

干杯

_auth0Client.PostToken<Auth0Auth>(tokenUrl, data, cancellationToken);

PostTokendata作为object jsonObject并将其传递给GenerateTokenRequestMessage然后创建 HTTP 内容:

var serializedObjectToCreate = JsonConvert.SerializeObject(objectToPost, new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
});

httpRequestMessage.Content = new StringContent(serializedObjectToCreate);
httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

但是在这里,您将输入序列化为 JSON 的数据,并期望它是application/x-www-form-urlencoded 但显然情况并非如此。 您正在生成的内容如下所示:

{"grant_type":"client_credentials","client_id":"ClientId","client_secret":"ClientSecret","audience":"Audience"}

但相反,它应该是这样的:

grant_type=client_credentials&client_id=ClientId&client_secret=ClientSecret&audience=Audience

您可以为此使用FormUrlEncodedContent类型:

httpRequestMessage.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
    ["grant_type"] = "client_credentials",
    ["client_id"] = _auth0HttpConfig.ClientId,
    ["client_secret"] = _auth0HttpConfig.ClientSecret,
    ["audience"] = _auth0HttpConfig.Audience,
});

由于您是从 dotnet 访问它,我建议使用 Auth0 NuGet package。

  1. 安装包 Auth0.AuthenticationApi
  2. 使用此基本代码作为您的真实代码的大纲以获得令牌
public class QuestionCode
{
    public async Task<string> GetToken()
    {
        var client = new AuthenticationApiClient("<your_auth0_domain>");
        var tokenRequest = new ClientCredentialsTokenRequest
        {
            ClientId = "<your_client_id>",
            ClientSecret = "<your_client_secret>",
            Audience = "<your_audience>",
        };

        var token = await client.GetTokenAsync(tokenRequest);
        return token.AccessToken;
    }
}

我针对虚拟 Auth0 API 进行了测试,它按预期工作。

快乐编码!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM