<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
    數據加載中……

    服務器端可控情形的Javascript跨域訪問解決方法

    2006-12-5

    ?

    我在最近的一個 web 項目中為了實現 bookmark 功能碰到了 javascript 跨域訪問的問題。起初,在 google 上搜的很多解決方案并不適用于我的情形,只在有一篇文章中提到的遠程加載 javascript 方法從理論上看到了解決的希望。但可惜作者只是一筆帶過,并未用例子詳細說明,所以不得不摸索了一陣才把這個問題搞定。在此,希望通過本文為同樣被這個問題困擾的朋友們提供一個解決方法作為參考。如有錯誤,歡迎指正!

    ?

    Bookmark 是目前許多 web2.0 網站 (http://del.icio.us/, www.diigo.com 等)都提供的熱門 feature 。它能將互聯網上自己喜歡的網頁收藏到 Bookmark 服務器上。本文要解決的問題就發生在用戶提交網頁 URL (還包括 Tag, Notes 等)給 Bookmark 服務器時。

    ?

    關于 URL 的提交至少可以有三種方式:

    ?

    1.?????? 登陸 Bookmark 服務器的提交頁面,將要收藏的 URL 通過該頁面提交給服務器。

    2.?????? 安裝瀏覽器插件,通過插件將 URL 提交給服務器。

    3.?????? Bookmark 服務器動態加載 javascript 小工具到當前頁面,通過它來完成提交工作。(參考 diigo 的例子,收藏一個網頁鏈接到瀏覽器收藏夾,鏈接的 URL 是一段 javascript 代碼,它會從服務器加載一段 javascript 注入當前網頁)

    ?

    第一種方式開發起來最簡單,但對用戶來講比較麻煩,每次都需要先登陸 Bookmark 服務器才能完成提交;第二種方式我并不熟悉插件開發,而且用戶也不喜歡太多的插件堆滿自己的瀏覽器;第三種方式開發難度小,又避免了每次登陸服務器的麻煩,所以我最終采用了它。

    ?

    上面講的第三種方式中動態加載的 javascript 小工具除了需要生成 UI 供用戶填寫信息( URL tag notes 等),當用戶點擊提交的時候,還要完成與服務器通信的功能。在沒有跨域訪問經驗的情況下,最先想到的當然是 ajax !但很快就會發現根本行不通。

    ?

    跨域訪問,簡單來說就是 A 網站的 javascript 代碼試圖訪問 B 網站,包括提交內容和獲取內容。由于安全原因,跨域訪問是被各大瀏覽器所默認禁止的。寫過跨域訪問 ajax 的朋友相信都遇到過被告知“沒有權限”的情況。通過 XMLHttp 來發送數據給 Bookmark 服務器的嘗試失敗了。于是,看到網上的一些資料,我又開始嘗試用 javascript 小工具在用戶網頁動態創建一個隱藏的 iframe, iframe src 指向服務器的一個 servlet ,試圖通過調用 iframe 中提供的 javascript 來完成與服務器的通信。但不幸的是,用戶網頁中的 javascript 代碼訪問 iframe 也被瀏覽器歸為跨域訪問(特指 iframe src 指向其它網站的情形),嘗試再次失敗。

    ?

    最終,在一篇文章中看到,與 iframe 不同,如果 A 網站從 B 網站加載 javascript A 網站可以自由的訪問該 javascript 的內容,并不會被瀏覽器認為是跨域訪問。模仿剛才 iframe 的思路,當用戶點擊提交時,可以動態創建一個 javascript 對象,該對象的 src 指向 Bookmark 服務器的一個 servlet ,注意: URL Tag Notes User Password 等信息被作為 src URL 參數傳給服務器。請看下面的代碼:

    ?

    var url = "http://localhost:8080/Deeryard/BookmarkServlet?" +

    ?????????? "url=" + url_source + "&" + "title=" + title + "&" +

    "tag=" + tag + "&" + "notes=" + notes + "&" + "user=" + user + "&" + "password=" + password;

    ?

    url = encodeURI(url);

    ???

    //Submit to server with a trick

    var js_obj = document.createElement( "script" );

    js_obj.type = "text/javascript" ;

    js_obj.setAttribute( "src" , url);

    ???

    //Get response from server by appending it to document

    document.body.appendChild(js_obj);

    ?

    上面例子中, js_obj.setArrribute() 將信息作為 src URL 參數提交給了 Bookmark servlet 。那么用戶又如何取得服務器的響應信息呢?答案就是最末一行代碼, servlet 的輸出必須是 javascript 代碼,它可以調用用戶網頁上的其他 javascript 函數,以及操作 dom 對象。下面的 servlet 代碼生成了一個 javascript 函數調用:

    ?

    out.write("onServerResponse(INADEQUATE_INFORMATION);");

    ?

    document.body.appendChild(js_obj) 執行后 onServerResponse( INADEQUATE_INFORMATION) 就會得到執行,使客戶網頁響應服務器結果。這樣一個完整的通信過程就完成了。

    ?

    來總結一下這個案例,首先與很多跨域訪問的情形不同,本文提到的跨域訪問需要對服務器端進行控制,即讓服務器端 Servlet 來適應客戶端網頁 javascript 的需求;而其他一些常見的例子則對服務器端沒有控制能力,比如從其他網站抓內容的小偷程序。另外,需要注意的是這種方法中實際用到了 get 方法來提交信息,從一些資料上看到, get 方法每次提交的信息不能超過 2k

    posted on 2006-12-05 22:48 weidagang2046 閱讀(9287) 評論(11)  編輯  收藏

    評論

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    IBM developerWorks上面有個文章,里面詳細講了ajax的三種數據傳輸機制,你上面這個實例就是其中的第三種方法。
    教程文章地址:
    http://www-128.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=110100
    需要注冊個ID才能閱讀。
    2006-12-06 09:27 | xinheqishi

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    我有個問題哦....
    比如,我第一次發送的時候創建一個script對象,然后在很斷的時間內發送了第二次,也就是創建了第二個script對象.那天他就把第一個覆蓋了,第一個怎么辦??

    但我又不能創建很多個script對象,那樣很占資源,只能刪除一些對象,那樣就又可能刪除寫沒有反會的對象......

    我的前提是我則個情求比較頻繁..

    希望能解我之惑...
    email: zuan8888@gmail.com
    2007-01-13 14:37 | 剎那

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    創建javascript對象的時候指定id屬性可以避免覆蓋;也可以按id查找對象來判斷是否已經返回,如果找到的話就可以看情況刪除。關于id的維護問題辦法應該很多。比如,維護一個全局計數器。

    如果一定要同步的話(比如,第一次返回才能發第二次),建議看看javascript的wait()函數。

    ps: 我的javascript經驗也不多,上面的建議還需要實踐檢驗。歡迎交流!
    2007-01-13 18:05 | weidagang2046

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    請問這種方式下客戶端(瀏覽器端)和Bookmark servlet端之間的關系是不是和直接通過瀏覽器訪問Bookmark servlet的關系是一樣的? 因為我想用這個方法來解決一個問題,A網站(應該是相當于這里的Bookmark servlet)負責控制邏輯,B網站負責頁面的外觀顯示.
    客戶端從B網站進入之后, 要動態創建javascript對象,提交多次請求, 而我想維護多個請求之間的狀態關系;是否和直接通過瀏覽器訪問B網站一樣,維持session就OK了?

    希望能解我之惑....謝謝!
    2007-01-13 19:28 | sparklet

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    因為Bookmark Servlet對javascript一無所知,只當成一般的網頁文本返回,所以我認為和一般瀏覽器的訪問沒有區別,用session維護狀態是完全可以的。
    2007-01-13 19:39 | weidagang2046

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    可行 跨域真是雙刃劍
    2007-02-04 11:42 | 小雨

    # re: 服務器端可控情形的Javascript跨域訪問解決方法[未登錄]  回復  更多評論   

    可以MSN交流嗎?tangcaiyou@hotmail.com
    2007-06-17 10:45 | eric

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    我嘗試了類似的代碼卻沒有成功。
    我在一個A網站的portlet中,iframe了一個B網站的jsp頁面,當點擊該jsp的某個鏈接后,我需要將一個參數傳送到A網站的某Servlet,可是沒有成功。
    代碼如下:
    site A的portlet:
    從IFrame中的頁面傳來的參數:<%=portlet_a_s%>
    <br/>
    <iframe width="300" height="300" src="http://siteB:7001/myWeb/B.jsp">
    </iframe>

    site B的jsp:
    <%@ page language="java" contentType="text/html;charset=UTF-8"%>
    <html>
    <head>
    <title>
    inner page
    </title>

    <script type="text/javascript">
    var lastScript;
    var h=document.getElementsByTagName("head")[0];

    function loadScript(url){
    var f=document.createElement("script");
    var d=new Date().getTime();
    f.type="text/javascript";
    f.id=d;
    f.src=url+'&date='+d;
    document.body.appendChild(f);
    if(lastScript&&g(lastScript))g(lastScript).parentNode.removeChild(g(lastScript));
    lastScript=d;
    }

    function g(x){
    return document.getElementById(x)
    }

    function onClickMeasureId(id){
    var hidden = g("hidden_input");
    hidden.value = id;
    var url = "http://siteA:7001/testWeb/portlets/portlet_a/PortletAServlet?id="+id;
    loadScript(url);
    }

    function onResponse(){
    alert("response");
    };
    </script>
    </head>
    <body>
    <a onclick="onClick('參數1')" href="#">參數1</a>
    </body>
    </html>

    siteA的Servlet:
    public class PorletAServlet extends HttpServlet
    {
    public void service(HttpServletRequest request,HttpServletResponse response){
    if ( request.getParameter("id") != null ){
    String id = request.getParameter("id").toString();
    HttpSession session = request.getSession();
    session.setAttribute("measure_id",request.getParameter("id") );
    try{
    response.setContentType("text/javascript");
    PrintWriter out = response.getWriter();
    out.write("onResponse();");
    }
    catch(Exception e){}
    }
    }
    }

    我執行siteA的portal,在siteA的servlet中加入斷點,點擊portlet中iframe中的鏈接,發行servlet并沒有得到執行。實在不知道為何不成功。

    不知道博主可否提供更加完整的例子?謝謝!
    2007-06-22 14:57 | liao

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    @liao
    你的例子應該沒有大問題,應該調查servlet沒有得到執行的原因。可以把url單獨拷貝出來,敲到瀏覽器的地址欄中試試看servlet能否執行。我估計是url本身的問題,很可能沒有真正對應到那個servlet。
    2007-06-22 16:31 | weidagang2046@gmail.com

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    你好我 我碰到了一個問題

    和你的說的類似

    希望你幫我看下

    多謝了 http://so.hr33.com/SearchResult.aspx?key=a&companyname=&zw=100&dq=100&sj=90&xl=10&jy=0&sex=2&age=0&yx=0&xz=0&hy=0&RCount=29&Page=1&type=1

    你點申請后點關閉就會提示 "拒絕訪問.."

    MAIL 我 colvinliu@qq.com
    2007-12-20 17:06 | colvinliu

    # re: 服務器端可控情形的Javascript跨域訪問解決方法  回復  更多評論   

    轉了一大圈 終于在這里找到了解決方法
    2010-04-22 11:21 | 唐兵

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 999久久久免费精品播放| 国产免费资源高清小视频在线观看| 亚洲图片中文字幕| 国产精品四虎在线观看免费| 成人免费区一区二区三区 | 亚洲最大福利视频| 亚洲AV蜜桃永久无码精品| 国产精品免费观看调教网| 亚洲精品无码少妇30P| 亚洲人成色7777在线观看| 啦啦啦高清视频在线观看免费 | 国产精品美女久久久免费| 亚洲人成7777影视在线观看| 亚洲精品高清一二区久久| 免费大片黄在线观看yw| a级毛片免费观看网站| 亚洲AV无码一区二区三区牛牛| a级亚洲片精品久久久久久久| 国产h视频在线观看网站免费| 国产日韩在线视频免费播放| 亚洲不卡视频在线观看| 亚洲日韩av无码| 国产精品久久香蕉免费播放| 在线观看www日本免费网站| 二级毛片免费观看全程| 亚洲精品无码日韩国产不卡av| 亚洲va在线va天堂va不卡下载| 免费午夜爽爽爽WWW视频十八禁| 国产成人免费高清激情明星| 99久久婷婷免费国产综合精品| 国产成人精品日本亚洲专| 国产亚洲3p无码一区二区| 免费人成在线观看播放国产| 成人网站免费观看| 日韩精品人妻系列无码专区免费| 一级A毛片免费观看久久精品| 亚洲av午夜国产精品无码中文字| 亚洲制服丝袜一区二区三区| 久久亚洲国产视频| 亚洲乱码无码永久不卡在线 | 永久黄网站色视频免费直播|