保护对Web服务的JavaScript请求

时间:2013-07-08 16:35:42

标签: javascript asp.net json

我有一个带有JSon脚本的页面,当按下按钮时会触发该脚本。该脚本使用Web服务。为了安全起见,后面的页面代码生成一个脚本,该脚本包含一个包含生成代码的对象。然后将代码添加到页眉中。 Web服务应该验证此代码,但是当它尝试通过密钥获取标头值时,标头不存在(换句话说,标头不存在)。

生成代码和javascript对象的代码(在.cs文件中):

    string cacheKey = User.Identity.Name + ":securityTicket";
    string securityTicket = Guid.NewGuid().ToString();

    Cache[cacheKey] = securityTicket;

    string script = string.Format("SECURITY_TICKET = '{0}';", securityTicket);

    ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "securityKey", script, true);

添加标题的脚本(在.aspx文件中)

    function onInvoke(sender, args) {
        args.get_webRequest().get_headers()['securityTicket'] = SECURITY_TICKET;);
    }

后面的Web服务代码(asmx.cs或类似的东西)             HttpContext context = HttpContext.Current;

        string headerTicket = context.Request.Headers["securityTicket"];

        if (string.IsNullOrEmpty(headerTicket))
        {
            throw new SecurityException("Security ticket must be present.");
        }

        string cacheKey = context.User.Identity.Name + ":securityTicket";
        string cacheTicket = (string)context.Cache[cacheKey];

        if (string.Compare(headerTicket, cacheTicket, false) != 0)
        {
            throw new SecurityException("Security ticket mismatched.");
        }

问题是 context.Request.Headers [“securityTicket”] 为空。

有什么建议吗? 谢谢!

更新

网络服务:

namespace PV
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ScriptService()]
    public class UserService : System.Web.Services.WebService
    {
        [WebMethod]
        public bool ChangeUserPassword(object userID, object password)
        {
            EnsureTicket();
            return PV.WebMethods.ChangeUserPassword(userID, password);
        }

        private void EnsureTicket()
        {
            HttpContext context = HttpContext.Current;

            string headerTicket = context.Request.Headers["securityTicket"];

            if (string.IsNullOrEmpty(headerTicket))
            {
                throw new SecurityException("Security ticket must be present.");
            }

            string cacheKey = context.User.Identity.Name + ":securityTicket";
            string cacheTicket = (string)context.Cache[cacheKey];

            if (string.Compare(headerTicket, cacheTicket, false) != 0)
            {
                throw new SecurityException("Security ticket mismatched.");
            }
        }
    }
}

页面:

    <script type="text/javascript" language="javascript">
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_beginRequest(beginRequest);
    function beginRequest(sender, args) {
        prm._scrollPosition = null;
        postbackElement = args.get_postBackElement();
    }
    var postbackElement;
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest);
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);

    function pageLoaded() {
        Sys.Net.WebRequestManager.add_invokingRequest(onInvoke);
        if (typeof (postbackElement) === "undefined") {
            return;
        }
        if ((postbackElement.id).indexOf("btnSelect") !== -1) {
            $("html, body").animate({ scrollTop: "300px" });
        }
    }

    function ApplicationLoadHandler() {
        // InitScript is a custom function 
        // registered from the User Control
        if (typeof InitScript == 'function')
            InitScript();
    }

    if (Sys && Sys.Application) {
        Sys.Application.add_load(ApplicationLoadHandler);
        Sys.Application.notifyScriptLoaded();
    }

    function pageUnload() {
        Sys.Net.WebRequestManager.remove_invokingRequest(onInvoke);
    }

    function onInvoke(sender, args) {
        args.get_webRequest().get_headers()['securityTicket'] = SECURITY_TICKET;
        alert('Security ticket: ' + args.get_webRequest().get_headers()['securityTicket']);
    }
</script>

    <%
    Response.Write(@"
        <script>
        function ResetPassword() 
        {
            var password = document.getElementById(""password"").value;
            var id = document.getElementById(""ctl00_ctl00_ContentPlaceHolder1_cphContent_hdnUsrID"").value;
            var d = {""userID"" : id, ""password"" : password };
            $.ajax
            ({
                type: ""POST"",
                url: """ + "" + @"http://localhost:2297/wwwroot/Services/UserService.asmx/ChangeUserPassword"",
                data: JSON.stringify(d),
                contentType: ""application/json"",
                dataType: ""json"",
                success: function() 
                {
                    document.getElementById(""password"").value = '';
                    alert('Succes');
                    $(""" + "#ctl00_ctl00_ContentPlaceHolder1_cphContent_pnlChangePassword" + @""").fadeOut();
                    $(""html, body"").animate
                    (   {
                            scrollTop: $(""" + "#ctl00_ctl00_ContentPlaceHolder1_cphContent_pnlPerson" + @""").offset().top - 100
                        }, 1200);
                },
                error: function(msg) 
                {
                    if(msg === false) 
                    {
                        alert('Error');
                        return;
                    }
                }
            })
        }

        function passwordChanged_Succes() { 
            alert('Changed');
        }

        function passwordChanged_Failed() { 
            alert('Failed');
        }
        </script>"); %>

该页面还包含更新面板。

背后的页面代码:

private void GenerateSecurityTicket()
{
    string cacheKey = User.Identity.Name + ":securityTicket";
    string securityTicket = Guid.NewGuid().ToString();

    Cache[cacheKey] = securityTicket;

    string script = string.Format("SECURITY_TICKET = '{0}';", securityTicket);

    ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "securityKey", script, true);
}

protected void Page_Load(object sender, EventArgs e)
{
    this.GenerateSecurityTicket();
}

1 个答案:

答案 0 :(得分:1)

因此。我的文件看起来像这样:

<强> Students.aspx

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <asp:ServiceReference Path="~/UserService.asmx" />
    </Services>
</asp:ScriptManager>
<script type="text/javascript" language="javascript">
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_beginRequest(beginRequest);
    function beginRequest(sender, args) {
        prm._scrollPosition = null;
        postbackElement = args.get_postBackElement();
    }
    var postbackElement;
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest);
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);

    function pageLoaded() {
        Sys.Net.WebRequestManager.add_invokingRequest(onInvoke);
        if (typeof (postbackElement) === "undefined") {
            return;
        }
    }

    function ApplicationLoadHandler() {
        // InitScript is a custom function 
        // registered from the User Control
        if (typeof InitScript == 'function')
            InitScript();
    }

    if (Sys && Sys.Application) {
        Sys.Application.add_load(ApplicationLoadHandler);
        Sys.Application.notifyScriptLoaded();
    }

    function pageUnload() {
        Sys.Net.WebRequestManager.remove_invokingRequest(onInvoke);
    }

    function onInvoke(sender, args) {
        args.get_webRequest().get_headers()['securityTicket'] = SECURITY_TICKET;
    }
</script>
<%Response.Write(@"
        <script>
        function rez() {
            alert('Success!');
        }
        function error(e) {
            alert(e.get_message());
            return;
        }
        function ResetPassword() 
        {
            var password = {the new password loaded from a textbox}
            var id = {the user id}
            UserService.ChangeUserPassword(id, password, rez, error);
        }
        </script>"); %>

<强> UserService.asmx

<%@ WebService Language="C#" CodeBehind="~/App_Code/UserService.cs" Class="UserService" %>

<强> UserService.cs

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class UserService : System.Web.Services.WebService
{
    public UserService()
    {
    }

    [WebMethod]
    public void ChangeUserPassword(object userID, object password)
    {
        EnsureTicket();
        PV.WebMethods.ChangeUserPassword(userID, password);
    }

    private void EnsureTicket()
    {
        HttpContext context = HttpContext.Current;

        string headerTicket = context.Request.Headers["securityTicket"];

        if (string.IsNullOrEmpty(headerTicket))
            throw new SecurityException("Security ticket must be present.");

        string cacheKey = context.User.Identity.Name + ":securityTicket";
        string cacheTicket = (string)context.Cache[cacheKey];

        if (string.Compare(headerTicket, cacheTicket, false) != 0)
            throw new SecurityException("Security ticket mismatched.");
    }
}

就是这样。应该工作(如果我没有忘记复制一些代码)。对我而言。