JSONP跨域訪問實現登錄驗證


最近在做一個手機Web項目,硬着頭皮上了。現在比較流行的就是使用Phonegap+HTML5+CSS+JS/JQuery做一個看起來native的mobile web app。但是由於時間急,而且這些東西都不是很熟悉,再加上這只是對已有web網站的mobile化,因此采用了Phonegap+幾乎純server端頁面的方式,做起來省事多了,但是缺點還是有一大堆的,這里就不細說了。

嘮叨之前首先聲明一點,本人不是教授,也沒有大量研究過,因此如有說錯的地方,請指出,不甚感謝。

好了,這篇隨筆要展示的是跨域訪問的一種實現,這是針對傳統ajax不支持跨域訪問而提出的。當然你也可以用別的技術實現跨域訪問,比如說websocket,只是這種實現比較費lib。只用一個2Kb的jsonp包就能跨域訪問,何樂而不為呢。

首先來說說啥叫跨域訪問,即由於瀏覽器的安全,不允許訪問不同域下的資源,通俗的說,A網站的資源不允許被B網站所使用(這個必須的,誰會允許別人來自己那蹭吃又蹭喝,甚至還打包帶走)。不過這也不是絕對的,偶爾借個螺絲刀也是可以的,像a標簽的href,script標簽的src,form表單的action屬性等都是可以“借”東西的。

對於jsonp真正的原理,目前也沒有很深入的去了解過。至於百度上搜的什么原理,說的都不對。比如“使用script標簽加載配置對象中的跨域url”,我想說的是為什么ajax就不能加載跨域url呢。而且我發現一個怪事,同樣使用$.getJson()進行JSONP跨域訪問,如果type為get,則可以跨域訪問,但如果改成post,則不行了。

好了,我們還是開始這個例子吧,理論什么的還是等有空google去吧。

首先理一下簡單的需求,就是本地html可以登錄到server端進行驗證,而且登錄后還應該是在本地,這是一個典型的跨域訪問。

用到的技術:

前台采用HTML+CSS+JQuery + JQuery Mobile(界面ui,用起來爽,但是侵入性太強,有時候讓人討厭),即做成一個mobile web app,可以在手機上進行登錄,需要使用Phonegap進行打包。

后台采用純粹的servlet進行處理,使用tomcat做web服務器。

哦,忘了jsonp是主角了,那就趕緊先拉出來溜溜吧。先上登錄頁面,我們那可愛的jsonp就被用到submit按鈕上(這不廢話么)。注意一點,如果你不是js大神,那么使用jquery的方法$.json(...)是沒法實現error方法的回調的,即如果服務器壓根沒開,要請求的登錄驗證url根本不能訪問,$.json()方法努力嘗試,發現不行,於是果斷不通知你就撤了。解決的方法是使用jquery-jsonp插件,一個大小只有2K的“高科技”啊,當然大神可以自己實現(我還是默默的飄過吧)。

function logon()
{
   var _url = createReqUrl();
   if(!_url)return false;
   //alert(_url);
   showWaiting();
   
   $.jsonp({
       url: _url,
       timeout: 5000,
       success: function(jsonData){
           if(jsonData[0].success=='true'){
               saveUserID(jsonData[0].retuid);
               //redirect
               turnToMenuPage();
           }else{
               $("#showError").html(jsonData[0].errorinfo);
               showSubmit();
           }
       },
       error: function(xOptions,textStatus){
           $("#showError").html(textStatus);
           showSubmit();
       }
   });
}

這個方法可謂是前台登錄的要害了。要做的事情是:

1.獲取web服務器地址配置頁面中的值(存儲在window對象的localStorage中,這是html5支持的本地存儲的方式之一),再加上表單輸入框的值,最后拼接成一個url。注意這個url要帶上“callback=?”,以方便后面$.jsonp的使用(當然也不是必須要這樣做的,這邊不寫后面可以補不足)。

2.豬腳粉墨登場,具體api可以參見 https://github.com/jaubourg/jquery-jsonp/blob/master/doc/API.md (1中提到的可以通過參數callbackParameter來彌補)。由於插件作者的NB,error回調方法可以使用了。

我想說的是跨域訪問不是那么easy的,需要雙方的配合。

首先,url中回調參數()的name跟后台的獲取參數名字要一致。這里,我有必要詳細的說明。

前台中,$.jsonp({

    url:"http://xxxxx.jsp?aa=bb&cc=dd&&callback=?" //你看到的是?,但其實使用的是默認的_jqjsp,自己參看jsonp插件的api吧

    success:function(){..}, //這個回調函數應該是眾望所歸,后台輸出的script腳本,其實基本上回調的就是他

    error:function(){...} //上面的豬腳掛了,就由他當替補,比如服務器根本沒開

}

上面斜體加粗部分都是可以由用戶指定的,是可以替換的,但是他們換了,服務器端也得換。所以除非吃飽了撐着,否則。。。你懂的。

后台,獲取回調方法名使用老掉牙的request.getParameter("callback"),輸出的script要形如?({aa:"bb",cc:"dd"})。

這么做,前后台就跟親戚一樣了,大家互相交流嘛。

奉上后台servlet的代碼,讓他們真正交流起來吧,哈哈。

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        
        String userID = null,password = null,jsonpCallBack = null;
        
        userID = req.getParameter("userid");
        password = req.getParameter("password");
//回調方法名要要一致 jsonpCallBack
= req.getParameter("callback"); String retJSONPStr = null;
//如果登錄過了,就不要瞎起哄了,回家待着吧。
if(userID!=null&&req.getSession().getAttribute(userID)!=null){ retJSONPStr = UserValidService.doLogoned(); retJSONPStr = JSONStrUtil.createRetJSONP(jsonpCallBack, retJSONPStr); }else{
//sbRetJSON :正確的翻譯是 傻逼返回json(返回的傻逼json) StringBuffer sbRetJSON
= new StringBuffer(); UserBean retUser = new UserBean(); //流氓是不允許登陸的 Boolean isSuccess = UserValidService.doValidation(userID, password,sbRetJSON,retUser); if(isSuccess){ req.getSession().setAttribute(userID, retUser); } retJSONPStr = JSONStrUtil.createRetJSONP(jsonpCallBack, sbRetJSON.toString()); } PrintWriter out = resp.getWriter(); //System.out.println(retJSONPStr);
//告訴前台,快遞到了 out.println(retJSONPStr); }

OK,例子就講到這里。至於代碼的話,如果有空就上傳了。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM