解決項目中的跨域操作問題


瀏覽器存在許多安全策略,其中同源策略就是其中一個,所謂同源策略也叫同域名策略,即只有協議+域名+端口一致的情況下才可以相互訪問,其目的就是為了保護用戶信息的安全,同源策略現在的范圍包括三方面:1)、Cookie、LocalStorage、IndexDB無法讀取;2)、DOM無法獲取;3)、AJAX請求不能發送。這里主要介紹兩種解決AJAX請求不能發送的解決方案:JSONP和CORS。JSONP是一種前端的解決方式;CORS是跨域資源共享,在服務端實現。

一、JSONP

 這里使用jquery的$.ajax()方法來實現JSOP跨域訪問,其代碼如下,

$(document).ready(function() {
        $('#btn').on('click', function() {
            $.ajax('http://localhost:8081/springmvc/my/my2/1/1',
                    {
                dataType : 'jsonp',
                type : 'get',
                jsonpCallback: "aa",
                success : function(data,status) {
                    console.log('111:'+data.Hello+' '+data);
                }
            })
        })
    })

這里使用jquery通過給一個按鈕注冊一個點擊事件來觸發跨域操作,具體看ajax()函數中的參數,第一個指定了一個URL(restful的形式),然后是必須指定dataType為jsonp,指定請求的類型為get,接着jsonCallBack參數指定為aa,這里這個參數的鍵及鍵值都可以隨便指定,然后是成功之后的回調函數,實現了控制台打印。

下面是后台代碼:

@RequestMapping("my2/{courseId}/{name}")
    @ResponseBody
    public String method2(@PathVariable("courseId") String courseId,@PathVariable("name") String name){
       //必須是這種形式的字符串,其中小括號內的字符串必須是標准的json格式的
String str
="aa({\"Hello\":\"World\"})";
return str; }

這里簡單的返回了一個字符串,可以看到字符串的形式比較特別,會發現很像JavaScript中的函數調用(aa({"Hello":"World"})),函數aa的形參是一個對象,恭喜你,這里確實是函數的調用,且函數名稱必須和前邊的jsonCallBack參數定義的值一致,在前端請求的時候的參數jsonCallBack的值即是這里的函數名。

其實jsonp的方式就是會動態的執行js代碼,從而實現跨域。

這種方式必須是get方式的請求,且在后台需要動態獲得一個參數的值,即jsonCallBack的值,獲得此參數的值之后和要返回的字符串進行拼接;如果要傳的參數比較多,這種方式就可以了。

二、CORS

CORS是跨域資源共享,通過設置響應頭的Access-Control-Allow-Origin屬性,從而控制跨域資源訪問,通常Access-Control-Allow-Origin的值可以設為“*”,代表對所有的域都可以實現跨域,也可以單獨設置為某個域,如http://10.10.18.98:9090,則表示這個域可以跨域訪問。

由於需要給響應設置Access-Control-Allow-Origin屬性,這里使用filter,代碼如下

package com.cn.my.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CORSFilter implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }
    //實現向響應頭部添加Access-Control-Allow-Origin屬性,實現跨域訪問。
    @Override
    public void doFilter(ServletRequest sRequest, ServletResponse sResponse,
            FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        
        
        HttpServletRequest request=(HttpServletRequest)sRequest;
        
        HttpServletResponse response=(HttpServletResponse)sResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        
        chain.doFilter(sRequest, sResponse);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}

以上是一個filter,可以對所有的域進行跨域訪問本域。下面是filter的配置,

<!--跨域訪問-->
    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.cn.my.filter.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

以上是在web.xml中進行的filter的配置,配置了服務端的跨域訪問,在前端可以使用普通的ajax進行訪問,

$('#btn').on('click', function() {
            $.ajax('http://localhost:8081/springmvc/my/my2/1/1',
                {
                type : 'get',
                success : function(data,stats) {
                    console.log('111:'+data.sex+' '+data);
                }
                

            })
        })

上面的ajax請求是一般的請求,,同樣可以獲得后台的值,且后台代碼不需要返回特定的字符串,后台只需要返回JSON即可。如下,

@RequestMapping("my2/{courseId}/{name}")
    @ResponseBody
    public Map<String,String> method2(@PathVariable("courseId") String courseId,@PathVariable("name") String name){
        HashMap<String,String> map=new HashMap<String,String>();
        map.put("name", "劉三");
        map.put("sex", "女");
        map.put("age", "47");
        return map;
    }

上面是返回json的后台方法,沒有任何的改變。

使用CORS的方式在IE10之下的瀏覽器是不支持的,下面是一張從網上download的圖,可以看到CORS的瀏覽器的支持情況,

 

通過兩種不同方式的比較可以看出,JSONP對老瀏覽器支持比較好,但使用起來稍微麻煩,CORS的方式配置簡單,只需要一個Filter即可,但是需要較新的瀏覽器,值得慶幸的是,現在大多數瀏覽器都支持了CORS。

有不正之處歡迎指正!謝謝!


免責聲明!

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



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