【问题标题】:ajax call passing securityajax 调用传递安全性
【发布时间】:2013-11-05 00:56:48
【问题描述】:

我正在尝试对返回 json(不是 jsonp)的页面进行 ajax 调用(使用 IE 10),但我不断收到“401 - 未经授权:由于凭据无效而拒绝访问”。该站点在 IIS 中设置为使用“Windows 身份验证”,但是,如果我更改站点以启用匿名身份验证,则该调用有效。下面是我用来拨打电话的代码。我的电话缺少什么或者我需要在我的网络服务器上更改什么? Windows 身份验证当前设置为在 Windows 身份验证上使用 NTLM 身份验证。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="scripts/jquery-2.0.3.min.js"></script>
    <script src="scripts/base64.js"></script>
    <script type="text/javascript">
        function QueryMyData() {
            var postUrl = 'http://mydevpage/storage.ashx';
            var data = 'AssetNumber=102405';
            $.support.cors = true;
            $.ajax({
                type: "POST",
                url: postUrl,
                data: data,
                dataType: 'json',
                crossDomain: true,
                cache: false,
                username: "mydomain.net\\myuser",
                password: "password",
                beforeSend: function (xhr) {
                    xhr.withCredentials = true;

                },
                success: function (result) {
                    if (result) {
                        if (result.error)
                            alert(result.error);
                        else
                            alert(result.id);
                    }
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    alert('Unknow Error:' + thrownError + ajaxOptions + xhr.status + " " + xhr.statusText);
                }
            });
        }
        QueryMyData();
    </script>
</head>
<body>
</body>
</html>

【问题讨论】:

  • 嗯,一件事是"mydomain.net\myuser" 可能是错误的;那可能应该是"mydomain.net\\myuser"
  • username = "mydomain.net\myuser", 和以下行无效,crossDomain 不需要,$.support.cors 不需要,scripts/jquery-2.0.3.min.js 不起作用IE8 和 CORS 在没有插件的情况下无法在带有 jQ​​uery 的 IE8 中工作。这里有很多错误。
  • 另一个是username : "...",应该是,而不是username = "...",
  • 感谢 cmets。我进行了建议的更改并在 IE 10 和 Chrome 中进行了尝试,但仍然没有运气。我仍然收到相同的 401 错误。其他想法?
  • 这个页面在哪个域上? mydevpage?你还有crossDomain 设置。

标签: javascript jquery ajax security


【解决方案1】:

我找到了解决问题的方法。虽然我无法让 ajax 请求与安全性命中另一个域上的页面一起工作,但我确实找到了一种方法来实现这一点。我最终创建了一个 ProxyHandler.ashx 页面并使用 WebClient 设置请求的权限。

html页面

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <script type="text/javascript">
        function QueryMyData() {
            var postUrl = './ProxyHandler.ashx?http://mydevpage/storage.ashx';
            var data = 'AssetNumber=102405';
            $.support.cors = true;
            $.ajax({
                type: "POST",
                url: postUrl,
                data: data,
                dataType: 'json',
                cache: false,
                success: function (result) {
                    if (result) {
                        if (result.error)
                            alert(result.error);
                        else
                            alert(result.id);
                    }
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    alert('Unknow Error:' + thrownError + ajaxOptions + xhr.status + " " + xhr.statusText);
                }
            });
        }
        QueryMyData();
    </script>
</head>
<body>
</body>
</html>

这里是代理页面(ProxyHandler.ashx)

public class ProxyHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        string username = "svcMyServiceAccount";
        string password = "password";
        try
        {
            string uri = context.Request.RawUrl.Substring(context.Request.RawUrl.IndexOf("?") + 1);

            if (uri.StartsWith("ping"))
            {
                context.Response.Write("<html><body>Hello ProxyHandler</body></html>");
                return;
            }

            context.Response.ContentType = "text/plain";

            byte[] bytes = new byte[context.Request.InputStream.Length];
            context.Request.InputStream.Read(bytes, 0, (int)context.Request.InputStream.Length);
            var data = System.Text.Encoding.UTF8.GetString(bytes);

            using (System.Net.WebClient wc = new System.Net.WebClient())
            {
                wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
                //this is the magic of getting auth passed.  See post http://stackoverflow.com/questions/1680718/domain-credentials-for-a-webclient-class-dont-work
                wc.Credentials = CreateCredientialCached(uri, username, password, "mydomain");
                var response = wc.UploadString(new Uri(uri, UriKind.Absolute), "POST", data);
                context.Response.Write(response); //already in the JSON Reponse class format
            }
        }
        catch (Exception e)
        {
            context.Response.Write(GetJSON(string.Empty, e));
        }
    }

    private CredentialCache CreateCredientialCached(string uri, string userName, string userPassword, string domain)
    {
        CredentialCache cc = new CredentialCache();
        cc.Add(new Uri(uri), "NTLM", new NetworkCredential(userName, userPassword, domain));
        return cc;
    }

    private string GetJSON(string id, Exception error)
    {
        var json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(new Response() { id = id, error = error != null ? error.ToString() : string.Empty });
        return json;
    }

    // Necessary for IHttpHandler implementation
    public bool IsReusable
    {
        get { return false; }
    }

    private class Response
    {
        public string id { get; set; }
        public string error { get; set; }
    };
}

【讨论】:

  • 虽然我的情况并不完全一样,但您的回答确实让我使用 WebClient 来解决与 cors 相关的 ajax 问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 2014-03-25
相关资源
最近更新 更多