1

我在 REST Web 服务领域是全新的,我在网络上浏览了大量文章,试图在 ASP.NET 中实现 REST Web 服务(同时在另一个项目中使用 Webform 应用程序)

我想知道 WebServices 有多安全?我设置的教程在这里解释:http: //www.codeproject.com/Articles/128478/Consuming-WCF-REST-Services-Using-jQuery-AJAX-Call

我可以用 jquery 调用我的 web 服务,但没有安全性。

我必须放置一个安全的 HTTP 标头吗?如果是这样,怎么做?

我想知道的另一件事:看html页面源代码的人会很容易找到“密码”或“登录”/“密码”吗?

需要你的帮助:(谢谢

编辑 :

我使用此代码通过 jquery 调用我的 Rest 服务:

function setHeader(xhr) {
    var secretkey = "userid:uCMfSzkjue+HSDygYB5aEg==";
    var hashedUrl = secretkey;
    var hashedUrlBase64 = hashedUrl.toString();
    xhr.setRequestHeader('Authorization', hashedUrlBase64, "1234dgt");
}

$.ajax({
    cache: false,
    type: "GET",
    async: false,
    url: rootWS + "ListeService/GetListeSerie" + "(" + listeId + ")",
    //data: "{'id':'" + listeId + "'}",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (response) {
                ...
    },
    error: function (msg) {
        ...
    },
    beforeSend: setHeader

});

并将此代码添加到我的 REST WS 中:

[WebInvoke(Method = "GET", UriTemplate = "GetListeSerie({id})")]
public List<SeriePourListe> GetListeSerie(string id)
{
    if (!Security.AuthenticateUser())
    {
        WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
        return null;
    }

    //do some stuff
}

public static class Security
{
    public static bool AuthenticateUser()
    {
        WebOperationContext ctx = WebOperationContext.Current;
        string requestUri = ctx.IncomingRequest.UriTemplateMatch.RequestUri.ToString();
        string authHeader = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization];
        // if supplied hash is valid, user is authenticated
        if (IsValidUserKey(authHeader, requestUri))
            return true;
        return false;
    }
    public static bool IsValidUserKey(string key, string uri)
    {
        string[] authParts = key.Split(':');
        if (authParts.Length == 2)
        {
            string userid = authParts[0];
            string hash = authParts[1];
            if (ValidateHash(userid, uri, hash))
                return true;
        }
        return false;
    }

    private static bool ValidateHash(string userid, string uri, string hash)
    {
        if (!UserKeys.Contains(userid))
            return false;
        string userkey = userid;
        byte[] secretBytes = ASCIIEncoding.ASCII.GetBytes(userkey);
        HMACMD5 hmac = new HMACMD5(secretBytes);
        byte[] dataBytes = ASCIIEncoding.ASCII.GetBytes(uri);
        byte[] computedHash = hmac.ComputeHash(dataBytes);
        string computedHashString = Convert.ToBase64String(computedHash);
        return computedHashString.Equals(hash);
    }
}
4

2 回答 2

2

取决于所需的安全级别。从 jQuery 调用确实会打开您的代码以供检查,并且可能不安全。一种选择是使用从 jQuery 调用的代理页面,然后代理页面与 Web 服务进行通信。此时可以设置代理页面以根据调用 ip、主机、隐藏表单字段值等来限制访问。

另一个建议是对所有请求参数进行 Base64 编码。不是超级安全,但需要更多的工作来窥探解码。

如果您的表单是安全的(例如需要登录才能访问),将当前用户 ID 传递给 Web 服务,然后在执行任何其他处理之前执行查找以确定该用户是否存在于 Web 服务中是最理想的。

Web 服务就是它们,对公众开放。如果返回的信息是安全的,则必须使用凭据进行访问。但是,如果您没有任何限制(例如登录以访问调用页面),则从 jQuery 开始,它总是容易受到攻击。

这些只是选项。希望能帮助到你。

=================附加示例:

代理页面 (.aspx)

protected void Page_Load(object sender, EventArgs e) {
        string result = "";


        if (Request.QueryString["srvcmethod"] != null && Request.QueryString["encodedJSONdata"] != null) {

             string decodedJSONRequest = encoder.StringFromBase64(Request.QueryString["encodedJSONdata"].ToString().Trim());
             string wsdlData = GetWebservice("ccAddressAPI", Request.QueryString["srvcmethod"].ToString().Trim(), decodedJSONRequest);

             /*
              * Existance of QueryString('callback') indicates a request initiated from JQuery AJAX on remote server
              * response must be formatted as JSONP to prevent parse failure (eg 'callback(JSON);' )
             */   
             if (Request.QueryString["callback"] != null) {
                 string jsonpCallBack = Request.QueryString["callback"];
                 result = jsonpCallBack + "(" + wsdlData + ");";
             } else {
                 result = wsdlData;
             }

             Response.Write(result);
             Response.End();
         }
    }

    /// <summary>
    /// Performs post to WebService
    /// </summary>
    /// <param name="srvc">Service File Name</param>
    /// <param name="srvcMethod">Method within service to call</param>
    /// <param name="jsonData">JSON Serialized form data</param>
    /// <returns>JSON Serialized string of webservice response</returns>
    private string GetWebservice(string srvc, string srvcMethod, string jsonData) {
        string result = null;
        string wsdlData = null;
        Dictionary<string, object> obj = new Dictionary<string, object>();

        //--define webservice url
        string currentReq = Request.Url.GetLeftPart(UriPartial.Authority);
        string servicepath = "/websrvc/";
        string wsdl = currentReq + servicepath + srvc + ".svc/" + srvcMethod;

        //--initiate webservice request
        try {
            byte[] postData = Encoding.UTF8.GetBytes(jsonData);
            WebRequest request = WebRequest.Create(wsdl);
            request.Method = WebRequestMethods.Http.Post;
            request.ContentLength = postData.Length;
            request.ContentType = "text/json";
            Stream dataStream = request.GetRequestStream();
            dataStream.Write(postData, 0, postData.Length);
            dataStream.Close();

            //--retrieve/store request response
            WebResponse response = request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());
            wsdlData = reader.ReadToEnd();
            reader.Close();
            response.Close();

        } catch (Exception ex) {
            logErrors(ex, System.Reflection.MethodBase.GetCurrentMethod().Name);
        }

        return wsdlData;
    }

调用代理页面的jQuery示例

var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(input){var output="";var chr1,chr2,chr3,enc1,enc2,enc3,enc4;var i=0;input=Base64._utf8_encode(input);while(i<input.length){chr1=input.charCodeAt(i++);chr2=input.charCodeAt(i++);chr3=input.charCodeAt(i++);enc1=chr1>>2;enc2=((chr1&3)<<4)|(chr2>>4);enc3=((chr2&15)<<2)|(chr3>>6);enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64}else if(isNaN(chr3)){enc4=64}output=output+this._keyStr.charAt(enc1)+this._keyStr.charAt(enc2)+this._keyStr.charAt(enc3)+this._keyStr.charAt(enc4)}return output},decode:function(input){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(i<input.length){enc1=this._keyStr.indexOf(input.charAt(i++));enc2=this._keyStr.indexOf(input.charAt(i++));enc3=this._keyStr.indexOf(input.charAt(i++));enc4=this._keyStr.indexOf(input.charAt(i++));chr1=(enc1<<2)|(enc2>>4);chr2=((enc2&15)<<4)|(enc3>>2);chr3=((enc3&3)<<6)|enc4;output=output+String.fro mCharCode(chr1);if(enc3!=64){output=output+String.fromCharCode(chr2)}if(enc4!=64){output=output+String.fromCharCode(chr3)}}output=Base64._utf8_decode(output);return output},_utf8_encode:function(string){string=string.replace(/\r\n/g,"\n");var utftext="";for(var n=0;n<string.length;n++){var c=string.charCodeAt(n);if(c<128){utftext+=String.fromCharCode(c)}else if((c>127)&&(c<2048)){utftext+=String.fromCharCode((c>>6)|192);utftext+=String.fromCharCode((c&63)|128)}else{utftext+=String.fromCharCode((c>>12)|224);utftext+=String.fromCharCode(((c>>6)&63)|128);utftext+=String.fromCharCode((c&63)|128)}}return utftext},_utf8_decode:function(utftext){var string="";var i=0;var c=c1=c2=0;while(i<utftext.length){c=utftext.charCodeAt(i);if(c<128){string+=String.fromCharCode(c);i++}else if((c>191)&&(c<224)){c2=utftext.charCodeAt(i+1);string+=String.fromCharCode(((c&31)<<6)|(c2&63));i+=2}else{c2=utftext.charCodeAt(i+1);c3=utftext.charCodeAt(i+2);string+=String.fromCharCode(((c&15)<<12)|((c2&63)<<6)|(c3&63));i+=3}}return strin g}}

    var data = JSON.stringify({
            "EmployeeId": EmployeeId,
            "LoginAccountId": LoginAccountId,
            "CustomerId": CustomerId,
            "CostCentreId": CostCentreId,
            "ParentCostCentreId": ParentCostCentreId,
            "CostCentreAdministratorId": CostCentreAdministratorId,
            "UserType": UserType,
            "optionValList": optionValList
        });

        var jsondata = Base64.encode(data);
        var srvcmethod = 'initCostCentreAddressDataProvider';
        $.ajax({
            url: "[proxypageurl.aspx]",
            type: "GET",
            cache: false,
            contentType: "application/json; charset=utf-8",
            dataType: "jsonp",
            data: { "srvcmethod": srvcmethod, "encodedJSONdata": jsondata },
            error: function (XMLHttpRequest, textStatus, errorThrown) { console.log({ 'XMLHttpRequest': XMLHttpRequest, 'textStatus': textStatus, 'errorThrown': errorThrown }); },
            success: function (jsonRes) {

                var json = JSON.parse(jsonRes);
        //additional processing here               
            }

        });

我讨厌用问题来回答问题,但是您的安全需求是什么,服务响应的返回类型是什么?

从后面的代码调用 Web 方法更加独立。唯一显着的区别是 Web 方法通常只能从调用页面或应用程序访问,除非您将响应格式化为 JSONP,否则无法从其他域获得。Web 服务是公开可用的,默认情况下通常返回 XML,但如果您从 Web 服务返回 JSON,它也将不可用于其他域,仅可用于您的域。

那么也许将您来自网络服务的响应格式化为 JSON?那时,即使我知道您的服务,我也无法调用它,除非您将其格式化为 JSONP。

上面的示例对 jQuery 使用 JSONP,因为我的 Web 服务位于与调用页面不同的域中。这可以修改为只返回 JSON,并且服务器端逻辑应该仍然有效(但是在那个用例中它是 UNTESTED)。

希望能有所帮助。

于 2013-05-16T17:56:16.837 回答
1

所以我编写了自己的代理,它似乎工作:

[System.Web.Services.WebMethod()]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static object Call(string WSUrl)
{
    // Create web client.
    WebClient client = new WebClient();
    client.Encoding = Encoding.UTF8;

    // Download string.
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    return serializer.Deserialize<List<object>>(client.DownloadString(WSUrl));
}

它可以用 jquery 来调用:

$.ajax({
    type: "POST",
    url: "http://localhost:14892/common/proxy.aspx/call",
    data: "{'WSUrl':'" + rootWS + "ListeService/2/GetListeSerie" + "(" + listeId + ")" + "'}",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (response) {
        var result = response.d;
        var new_record = "";
        $.each(result, function (index, res) {
            new_record = serieListe(index + 1, res.Id, res.ImageUrl, res.SerieNom, res.SerieSynopsis, res.SerieUrl);
            $('#gridElementsListe').append(new_record);
        });
    },
    error: function (msg) {
        $('#msg').html("Error while calling web service,,")
    }
});

希望它有所帮助。现在我将按照 bphillips 的建议为我的代理添加一些安全性。如果您对拥有良好的安全协议有任何建议,请不要犹豫在这里分享;)

于 2013-05-16T19:48:46.530 回答