简体   繁体   English

C# 调用 web api 时不支持的授权类型

[英]C# unsupported grant type when calling web api

I am trying to perform a Post to my WebAPI from a c# WPF desktop app.我正在尝试从 c# WPF 桌面应用程序向我的 WebAPI 执行发布。

No matter what I do, I get无论我做什么,我都会得到

{"error":"unsupported_grant_type"} {“错误”:“不支持的授权类型”}

This is what I've tried (and I've tried everything I could find):这是我尝试过的(并且我已经尝试了我能找到的一切):

Also dev web api currently active for testing: http://studiodev.biz/还开发 web api 目前正在测试中: http://studiodev.biz/

base http client object:基础 http 客户端 object:

var client = new HttpClient()
client.BaseAddress = new Uri("http://studiodev.biz/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));

with the following send methods:使用以下发送方法:

var response = await client.PostAsJsonAsync("token", "{'grant_type'='password'&'username'='username'&'password'='password'");
var response = await client.PostAsJsonAsync("token", "grant_type=password&username=username&password=password");

After that failed, I did some googling and tried:失败后,我做了一些谷歌搜索并尝试:

LoginModel data = new LoginModel(username, password);
string json = JsonConvert.SerializeObject(data);
await client.PostAsync("token", new JsonContent(json));

same result, so I tried:结果相同,所以我尝试了:

req.Content = new StringContent(json, Encoding.UTF8, "application/x-www-form-urlencoded");
await client.SendAsync(req).ContinueWith(respTask =>
{
 Application.Current.Dispatcher.Invoke(new Action(() => { label.Content = respTask.Result.ToString(); }));
});

Note: I can make a successful call with Chrome.注意:我可以使用 Chrome 成功拨打电话。

Update Fiddler Result更新提琴手结果

在此处输入图像描述

Could someone please help me make a successful call to the above web api... Please let me know if I can help clarify.有人可以帮我成功拨打上述 web api ... 如果我能帮助澄清,请告诉我。 Thanks!!谢谢!!

The default implementation of OAuthAuthorizationServerHandler only accepts form encoding (ie application/x-www-form-urlencoded ) and not JSON encoding ( application/JSON ). OAuthAuthorizationServerHandler的默认实现只接受表单编码(即application/x-www-form-urlencoded )而不接受 JSON 编码( application/JSON )。

Your request's ContentType should be application/x-www-form-urlencoded and pass the data in the body as:您请求的ContentType应该是application/x-www-form-urlencoded并将数据在正文中传递为:

grant_type=password&username=Alice&password=password123

ie not in JSON format .不是 JSON 格式

The chrome example above works because it is not passing data as JSON.上面的 chrome 示例有效,因为它没有将数据作为 JSON 传递。 You only need this for getting a token;你只需要这个来获取令牌; for other methods of your API you can use JSON.对于 API 的其他方法,您可以使用 JSON。

This kind of problem is also discussed here .此类问题也在此处讨论。

1) Note the URL: "localhost:55828/token" (not "localhost:55828/API/token") 1) 注意 URL:“localhost:55828/token”(不是“localhost:55828/API/token”)

2) Note the request data. 2) 注意请求数据。 Its not in json format, its just plain data without double quotes.它不是json格式,它只是没有双引号的普通数据。 "userName=xxx@gmail.com&password=Test123$&grant_type=password" “用户名=xxx@gmail.com&password=Test123$&grant_type=password”

3) Note the content type. 3) 注意内容类型。 Content-Type: 'application/x-www-form-urlencoded' (not Content-Type: 'application/json')内容类型:'application/x-www-form-urlencoded'(不是内容类型:'application/json')

4) When you use javascript to make post request, you may use following: 4) 当您使用 javascript 发出 post 请求时,您可以使用以下内容:

$http.post("localhost:55828/token", 
    "userName=" + encodeURIComponent(email) +
        "&password=" + encodeURIComponent(password) +
        "&grant_type=password",
    {headers: { 'Content-Type': 'application/x-www-form-urlencoded' }}
).success(function (data) {//...

See screenshots below from Postman:请参阅以下来自 Postman 的屏幕截图:

邮递员请求

邮递员请求标头

Here is a working example I used to make this request of my local Web API application running on port 43305 using SSL.这是一个工作示例,我曾经使用 SSL 向在端口 43305 上运行的本地 Web API 应用程序发出此请求。 I put the project on GitHub as well.我也把这个项目放到了 GitHub 上。 https://github.com/casmer/WebAPI-getauthtoken https://github.com/casmer/WebAPI-getauthtoken

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Net.Http;
using System.Web;

namespace GetAccessTokenSample
{
  class Program
  {
    private static string baseUrl = "https://localhost:44305";

    static void Main(string[] args)
    {

      Console.WriteLine("Enter Username: ");
      string username= Console.ReadLine();
      Console.WriteLine("Enter Password: ");
      string password = Console.ReadLine();

      LoginTokenResult accessToken = GetLoginToken(username,password);
      if (accessToken.AccessToken != null)
      {
        Console.WriteLine(accessToken);
      }
      else
      {
        Console.WriteLine("Error Occurred:{0}, {1}", accessToken.Error, accessToken.ErrorDescription);
      }

    }


    private static LoginTokenResult GetLoginToken(string username, string password)
    {

      HttpClient client = new HttpClient();
      client.BaseAddress = new Uri(baseUrl);
      //TokenRequestViewModel tokenRequest = new TokenRequestViewModel() { 
      //password=userInfo.Password, username=userInfo.UserName};
      HttpResponseMessage response =
        client.PostAsync("Token",
          new StringContent(string.Format("grant_type=password&username={0}&password={1}",
            HttpUtility.UrlEncode(username),
            HttpUtility.UrlEncode(password)), Encoding.UTF8,
            "application/x-www-form-urlencoded")).Result;

      string resultJSON = response.Content.ReadAsStringAsync().Result;
      LoginTokenResult result = JsonConvert.DeserializeObject<LoginTokenResult>(resultJSON);

      return result;
    }

    public class LoginTokenResult
    {
      public override string ToString()
      {
        return AccessToken;
      }

      [JsonProperty(PropertyName = "access_token")]
      public string AccessToken { get; set; }

      [JsonProperty(PropertyName = "error")]
      public string Error { get; set; }

      [JsonProperty(PropertyName = "error_description")]
      public string ErrorDescription { get; set; }

    }

  }
}

If you are using RestSharp, you need to make the request like this:如果您使用的是 RestSharp,则需要像这样发出请求:

public static U PostLogin<U>(string url, Authentication obj)
            where U : new()
        {
            RestClient client = new RestClient();
            client.BaseUrl = new Uri(host + url);
            var request = new RestRequest(Method.POST);
            string encodedBody = string.Format("grant_type=password&username={0}&password={1}",
                obj.username,obj.password);
            request.AddParameter("application/x-www-form-urlencoded", encodedBody, ParameterType.RequestBody);
            request.AddParameter("Content-Type", "application/x-www-form-urlencoded", ParameterType.HttpHeader);
            var response = client.Execute<U>(request);

             return response.Data;

        }

Had same issues but only resolved mine over secured HTTP for the token URL.有同样的问题,但仅通过令牌 URL 的安全 HTTP 解决了我的问题。 See sample httpclient code.请参阅示例 httpclient 代码。 Ordinary HTTP just stop working after server maintenance普通HTTP在服务器维护后就停止工作

var apiUrl = "https://appdomain.com/token"
var client = new HttpClient();    
client.Timeout = new TimeSpan(1, 0, 0);
            var loginData = new Dictionary<string, string>
                {
                    {"UserName", model.UserName},
                    {"Password", model.Password},
                    {"grant_type", "password"}
                };
            var content = new FormUrlEncodedContent(loginData);
            var response = client.PostAsync(apiUrl, content).Result;

it my case, im forget install install package Token.JWT, so you need install too in your project.在我的情况下,我忘记安装安装包 Token.JWT,所以你也需要在你的项目中安装。 Install-Package System.IdentityModel.Tokens.Jwt -Version 6.7.1安装包 System.IdentityModel.Tokens.Jwt -Version 6.7.1

It may be the cause of protocol it's required https://这可能是协议的原因,它需要 https://

EX : https://localhost:port/oauth/token例如:https://localhost:port/oauth/token

jQuery.ajax({ jQuery.ajax({

    "method": "post",
    "url": "https://localhost:44324/token",
    **"contentType": "application/x-www-form-urlencoded",**
    "data": {
      "Grant_type": "password",
      "Username": $('#txtEmail').val(),
      "Password": $('#txtPassword').val()
    }
  })
    .done(function (data) { console.log(data); })
    .fail(function (data) { console.log(data); })

//In Global.asax.cs (MVC WebApi 2) //在 Global.asax.cs (MVC WebApi 2)

protected void Application_BeginRequest()受保护的无效 Application_BeginRequest()

    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
        
    }

Output Output

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

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