如果数据是对象,则 OWIN 授权失败

OWIN Authorization fails if data is an object

这怎么行得通:

var data = "grant_type=password&client_id=" 
  + appSettings.authClientId 
  + "&username=" 
  + loginData.userName 
  + "&password=" 
  + loginData.password;

$http.post(
  appSettings.apiServiceBaseUri + "token", 
  data, 
  { headers: { "Content-Type": "application/json" } }
)

但这会产生 400 错误:clientId 为空:

var data = {
    grant_type: "password",
    client_id: appSettings.authClientId,
    username: loginData.userName,
    password: loginData.password
};

$http.post(
  appSettings.apiServiceBaseUri + "token", 
  data, 
  { headers: { "Content-Type": "application/json" } }
)

这是服务器端的代码:

public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
    string clientId;
    string clientSecret;

    if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
    {
        context.TryGetFormCredentials(out clientId, out clientSecret);
    }

OAuth 2.0 的 specification 要求您在 body 中发送参数:

HEADER:

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

BODY:

grant_type=password&username=johndoe&password=A3ddj3w

事实上,即使您更改 Content-Type (header):

,您的第一个请求也应该有效
var data = "grant_type=password&client_id=" 
  + appSettings.authClientId 
  + "&username=" 
  + loginData.userName 
  + "&password=" 
  + loginData.password;

$http.post(
  appSettings.apiServiceBaseUri + "token", 
  data, 
  { headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" } }
)

在您的第二个示例代码中,您的请求在 body 中,格式如下:

{"grant_type":"密码","用户名":"我的用户名","密码":"我的密码"}

而您的 ValidateClientAuthentication 无法解析它。

您可以使用 transformRequest 尝试另一种方法:

$http({
    method: 'POST',
    url: appSettings.apiServiceBaseUri + "token",
    headers: { 'Authorization': 'Basic ' + authorizationBasic }, 
    data: { username: loginData.userName, password: loginData.password, grant_type: 'password' },
    transformRequest: function (obj) {
    var str = [];
    for (var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
    return str.join("&");
    }
}).success(function (data, status, headers, config) {
    // deferred.resolve(data);
}).error(function (data, status, headers, config) {
    // deferred.reject("An error occured while fetching items");
});