繁体   English   中英

JQuery中具有FormURLEncodedContent而不是JSON的HttpClient PostAsync等效项

[英]HttpClient PostAsync equivalent in JQuery with FormURLEncodedContent instead of JSON

我编写了一个JQuery脚本来执行用户登录POST(试图完成我在附加信息部分中对C#所做的操作,请参见下文)。

在我的html页面中使用JQuery代码触发POST之后,我发现了以下问题:

1-我调试了服务器端代码,并且知道服务器已收到POST(在ValidateClientAuthentication()函数中,但在GrantResourceOwnerCredentials()函数中未收到 )。
2-同样,在服务器端,我找不到应该与postdata一起发布的用户名密码的任何迹象。 而使用用户端C#代码 ,当我调试到服务器端C#代码时 ,可以在上下文变量中看到这些值。 我认为,这就是问题的全部根源。
3- JQuery代码调用函数getFail ()。

-我想知道,这个JQuery代码与下面的C#用户端 代码有什么不同,我该如何解决它,使它们完成相同的工作?

我的猜测:JSON.stringifyFormURLEncodedContent做一些不同的事情)

jQuery / Javascript代码:

function logIn() {
var postdata = JSON.stringify(
{
    "username": document.getElementById("username").value,
    "password": document.getElementById("password").value
});

try {
    jQuery.ajax({
        type: "POST",
        url: "http://localhost:8080/Token",
        cache: false,
        data: postdata,
        dataType: "json",
        success: getSuccess,
        error: getFail
    });
} catch (e) {
    alert('Error in logIn');
    alert(e);
}
function getSuccess(data, textStatus, jqXHR) {
    alert('getSuccess in logIn');
    alert(data.Response);
};
function getFail(jqXHR, textStatus, errorThrown) {
    alert('getFail in logIn');
    alert(jqXHR.status); // prints 0
    alert(textStatus); // prints error
    alert(errorThrown); // prints empty
};

};

服务器端处理POST(C#):

public override async Task ValidateClientAuthentication(
        OAuthValidateClientAuthenticationContext context)
    {
        // after this line, GrantResourceOwnerCredentials should be called, but it is not.
        await Task.FromResult(context.Validated());
    }


public override async Task GrantResourceOwnerCredentials(
        OAuthGrantResourceOwnerCredentialsContext context)
    {
        var manager = context.OwinContext.GetUserManager<ApplicationUserManager>();

        var user = await manager.FindAsync(context.UserName, context.Password);
        if (user == null)
        {
            context.SetError(
                "invalid_grant", "The user name or password is incorrect.");
            context.Rejected();
            return;
        }

        // Add claims associated with this user to the ClaimsIdentity object:
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        foreach (var userClaim in user.Claims)
        {
            identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
        }

        context.Validated(identity);
    }

附加信息:在我的C#Owin Web服务器的C#客户端测试应用程序中,我具有以下代码来执行POST(正常工作):
用户端POST(C#):

//...
HttpResponseMessage response;
var pairs = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>( "grant_type", "password"), 
    new KeyValuePair<string, string>( "username", userName ), 
    new KeyValuePair<string, string> ( "password", password )
};
var content = new FormUrlEncodedContent(pairs);

using (var client = new HttpClient())
{
    var tokenEndpoint = new Uri(new Uri(_hostUri), "Token"); //_hostUri = http://localhost:8080/Token
    response = await client.PostAsync(tokenEndpoint, content);
}
//...

不幸的是, dataType控制jQuery期望返回的数据是什么,而不是什么data 要设置请求数据( data )的内容类型,请改用contentType: "json" (更多文档 。)

var postdata = JSON.stringify({“ username”:document.getElementById(“ username”)。value,“ password”:document.getElementById(“ password”)。value});

jQuery.ajax({
    type: "POST",
    url: "http://localhost:8080/Token",
    cache: false,
    data: postdata,
    dataType: "json",
    contentType: "json",  // <=== Added
    success: getSuccess,
    error: getFail
});

如果您不是要发送 JSON,而是想发送通常的URI编码的表单数据,则完全不用JSON.stringify ,而直接将对象提供给jQuery的ajax jQuery然后将创建URI编码的表单。

try {
    jQuery.ajax({
        type: "POST",
        url: "http://localhost:8080/Token",
        cache: false,
        data: {
            "username": document.getElementById("username").value,
            "password": document.getElementById("password").value
        },
        dataType: "json",
        success: getSuccess,
        error: getFail
    });
    // ...

稍微增加一下TJ的答案,将JSON发送到/token端点不起作用的另一个原因是,它不支持JSON。

即使将$.ajax's contentType选项设置为application/json ,就像将JSON数据发送到MVC或Web API一样, /token也不会接受该有效负载。 它仅支持表单URL编码对(例如,username = dave&password = hunter2)。 如果将对象传递给data选项,则$.ajax会自动为您进行编码,例如,如果postdata变量未经过JSON字符串化,则它会自动进行编码。

此外,您还必须记住在请求中包含grant_type=password参数(就像PostAsync()代码一样)。 否则,即使用户名和密码实际上正确, /token端点也将以“无效的授予类型”错误响应。

发送表单数据时,应使用jquery的$ .param对数据进行urlencode。 AngularJs的$ http方法当前不执行此操作。

喜欢

var loginData = {
            grant_type: 'password',
            username: $scope.loginForm.email,
            password: $scope.loginForm.password
        };

        $auth.submitLogin($.param(loginData))
          .then(function (resp) {
              alert("Login Success"); // handle success response
          })
          .catch(function (resp) {
              alert("Login Failed");  // handle error response
          });

从angularjs 1.4开始,这与$ httpParamSerializerJQLike无关紧要:

.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
    $http({
      method: 'POST',
      url: baseUrl,
      data: $httpParamSerializerJQLike({
        "user":{
          "email":"wahxxx@gmail.com",
          "password":"123456"
        }
      }),
      headers:
        'Content-Type': 'application/x-www-form-urlencoded'
    })
})

暂无
暂无

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

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