CORS解決跨域請求

前言

咱們有不少種方式解決跨域請求
本篇爲你們講解使用CORS解決跨域html

CORS又稱跨域資源共享
它須要瀏覽器和服務器的同時支持
在開發過程當中,瀏覽器並不會有過多的變化
服務器是關鍵,只有服務器實現了CORS接口,才能夠進行跨域請求前端

CORS對於瀏覽器發過來的AJAX跨域請求分爲兩種:
簡單請求和非簡單請求java

簡單請求

所謂簡單請求就是HEAD,GET,POST三種請求方式
瀏覽器會在在header信息裏面多加一個字段:
key:origin
value:協議+域名+端口(如https://localhost:8080)ajax

服務器根據對象裏的origin值來決定是否贊成此次請求spring

若是請求經過
請求經過後,服務器會在header裏多增長几個字段:json

Access-Control-Allow-Origin: https://localhost:8080
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Token

解釋:
1.Credentials是否容許包含cookie,若是返回了true,那麼瀏覽器發送請求體的時候要添加:後端

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

如此這般,才能向服務器發送cookie跨域

2.Access-Control-Expose-Headers是多返回的字段名,根據實際需求改變瀏覽器

若是請求失敗
說明以前發送Origin的value不在許可範圍內
服務器會返回一個正常的HTTP迴應
瀏覽器發現,這個迴應的頭信息沒有包含Access-Control-Allow-Origin字段
從而拋出一個沒法跨域的異常(多是200,因此沒法識別)緩存

非簡單請求

簡單請求的方法是Head,Get,Post
那麼非簡單請求的方法就是Put,Delete,或者Content-Type是application/json

非簡單請求在發出CORS請求以前,會增長一次HTTP查詢請求,也叫預檢請求
預檢請求成功了,瀏覽器才能發出XMLHttpRequest,不然報錯

若是瀏覽器發現這是一個非簡單請求
就會先發送一個預檢請求:

OPTIONS /cors HTTP/1.1
Origin: http://localhost:8088
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: token

預測請求的方法名叫OPTIONS
Origin和簡單請求同樣
Access-Control-Request-Method是請求方法
Access-Control-Request-Headers是額外發送的頭信息字段
(tip:預檢請求通常緩存下來,以便不須要在每次請求都發送)

若是預檢請求經過
咱們來看下服務器發出的迴應

HTTP/1.1 200 OK
Date: Nov, 01 Dec 2017 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://localhost:8088
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: token
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

若是預檢請求失敗
服務器會返回一個HTTP迴應(沒有CORS的頭信息字段)
並在console打出not allowed by Access-Control-Allow-Origin異常

預檢請求經過之後
瀏覽器發每次出的CORS請求就和簡單請求同樣
會有一個origin字段
服務器每次迴應都會有Access-Control-Allow-Origin頭信息字段

先後端代碼實現

前端jQuery寫法:

$.ajax({
    type: "POST",
    url: baseUrl + "/post",
    dataType: 'json',
    crossDomain: true,
    xhrFields: {
        withCredentials: true
    },
    data: {
        name: "name_from_frontend"
    },
    success: function (response) {
        console.log(response)// 返回的 json 數據
        $("#response").val(JSON.stringify(response));
    }
});

crossDomain: true是指開啓跨域

後端mvc配置類:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**/*").allowedOrigins("*");
    }
}

這是spring4.2以上版本

若是是4.2如下的:

public class CrossDomainFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.addHeader("Access-Control-Allow-Origin", "*");// 若是提示 * 不行,請往下看
        response.addHeader("Access-Control-Allow-Credentials", "true");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.addHeader("Access-Control-Allow-Headers", "Content-Type");
        filterChain.doFilter(request, response);
    }
}

4.2如下還需加過濾器:

<filter>
    <filter-name>CrossDomainFilter</filter-name>
    <filter-class>com.javadoop.filters.CrossDomainFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CrossDomainFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

以上即是CORS請求的原理;
以爲還能夠的請點個贊,贊不了也能夠收藏下;
總之,謝謝閱讀~

相關文章
相關標籤/搜索