ASP.NET MVC Ajax 表单提交跨域不发送Cookie

ASP.NET MVC Ajax form submitted cross domain not sending Cookies

我的网站有一些使用 ASP.NET MVC Ajax 的表单。 BeginForm 方法示例:

@using (Ajax.BeginForm("HandleSignin", "Profile", null, new AjaxOptions() { 
      HttpMethod = "POST", 
      Url = Url.Action("HandleSignin", "Profile", null, Request.Url.Scheme), 
      OnBegin = "SetWithCredentialsTrue(xhr)", 
      InsertionMode = InsertionMode.Replace, 
      UpdateTargetId = "signin-form-container" }, 
   new { id = "sign-in-form", @class = "text-left-desktop group" }))
{
    @Html.AntiForgeryToken()
    @Html.TextBoxFor(x => Model.Email, new { placeholder = "Email" })
    @Html.PasswordFor(x => Model.Password, new { placeholder = "Password" })
    <input type="submit" value="SignIn" class="button small-button">
}

请注意,由于 Url.Action 方法中的 Request.Url.Scheme 参数,URL 被设置为与浏览器从中获取此信息的域不同的域.这样做是因为主站点是使用 CDN 静态托管的,而表单是使用 AJAX 从另一个域加载的。这有效,除了 cookie 不在 AJAX 请求中发送。我试图通过使用 OnBegin 事件设置 xhr.withCredentials = true 和这个 JavaScript:

来发送 cookie
<script type="text/javascript">
    function SetWithCredentialsTrue(xhr) {
        console.log("SetWithCredentialsTrue(xhr)", xhr);
        xhr.withCredentials = true;
    }
</script>

虽然我可以看到调用了 SetWithCredentialsTrue() 方法,但它似乎不起作用,因为提交表单时生成的 HTTP 请求没有 Cookie header.

所有 server-side 处理程序都将 Access-Control-Allow-Credentials 响应 header 设置为 true,将 Access-Control-Allow-Origin 设置为主(静态)站点域。

更新: 通过更多控制台日志记录,我已验证传递给我的 OnBegin 事件处理程序 (SetWithCredentialsTrue) 的 xhr 参数不是XMLHttpRequest object and hence setting withCredentials对它没有影响。 所以问题是如何访问 XMLHttpRequest object?

根据我的理解,你想做的是,你想使用 AJAX post 将数据从一个域发送到另一个域,对吗?

如果这是真的,我想告诉你浏览器不允许你这样做,因为安全问题。

如果您仍然想这样做,那么您有两个选择,即使用 CORS 和 JSONP。

http://csharp-video-tutorials.blogspot.in/2016/09/calling-aspnet-web-api-service-in-cross.html

http://csharp-video-tutorials.blogspot.in/2016/09/cross-origin-resource-sharing-aspnet.html

我终于明白了。 XMLHttpRequest 对象未通过 ASP.NET MVC 库公开。我能够更改 jquery.unobtrusive-ajax.js,ASP.NET MVC 助手使用的 JS 库,以便将 withCredentials 设置为 true:

$(document).on("submit", "form[data-ajax=true]", function (evt) {
    var clickInfo = $(this).data(data_click) || [],
        clickTarget = $(this).data(data_target),
        isCancel = clickTarget && clickTarget.hasClass("cancel");
    evt.preventDefault();
    if (!isCancel && !validate(this)) {
        return;
    }
    asyncRequest(this, {
        url: this.action,
        type: this.method || "GET",
        data: clickInfo.concat($(this).serializeArray()),
        xhrFields: {
            withCredentials: true
        }
    });
});

注:xhrFields是我添加的部分。