取決於所需的安全級別。從jQuery調用確實會打開你的代碼spection,並且可能不安全。一種選擇是使用從jQuery調用的代理頁面,然後代理頁面與web服務進行通信。此時,代理頁面可以設置爲基於主叫IP,主機,隱藏表單字段值等限制訪問。
另一個建議是Base64對所有請求參數進行編碼。不是超級安全的,但需要更多的工作來撬動解碼。
如果您的表單是安全的(例如需要登錄才能訪問),請將當前用戶標識傳遞給webservice,然後在執行任何其他處理之前執行查找以確定該用戶是否存在於webservice中是最理想的。
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:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/=",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,則其他域也不可用,僅適用於您。
所以也許從web服務格式化您的響應爲JSON?在那一點上,即使我知道你的服務,我也無法調用它,除非你格式化爲JSONP。
上面的示例使用JSONP作爲jQuery,因爲我的webservice位於調用頁面的單獨域中。這可以修改爲僅返回JSON,並且服務器端邏輯應該仍然可以工作(但是在該用例中它是未測試的)。
希望有所幫助。
謝謝bphillips的幫助。我已經編輯我的問題來添加代碼示例。你說「將當前用戶ID傳遞給web服務」,但是如何避免在html/js源代碼中顯示userId?在我的示例中,您可以輕鬆找到secretkey「userid:uCMfSzkjue + HSDygYB5aEg ==」,並呼叫我休息WS :( – toregua
您認爲最佳做法是避免從jquery調用REST WS嗎?是更好地調用webmethod還是舊的代碼asmx WS?我完全失去了所有的解決方案... – toregua
你有一個代理頁面的例子嗎? – toregua