我和跨域的狗皮膏藥故事

跨域

談談跨域以前, 咱們先談談這幾個響應頭.javascript

Access-Control-Allow-Credentials : truehtml

Access-Control-Allow-Headers : *java

Access-Control-Allow-Methods: *web

Access-Control-Allow-Origin: baidu.comspring

redentials

access-Control-Allow-Credentials響應報頭指示的請求的響應是否能夠暴露於該頁面。當true值返回時它能夠被暴露。apache

憑證是 Cookie ,受權標頭或 TLS 客戶端證書。跨域

看成爲對預檢請求的響應的一部分使用時,它指示是否可使用憑證進行實際請求。請注意,簡單的GET請求不是預檢的,因此若是請求使用憑證的資源,若是此資源不與資源一塊兒返回,瀏覽器將忽略該響應,而且不會返回到 Web 內容。瀏覽器

Access-Control-Allow-Credentials的 header 文件與該XMLHttpRequest.withCredentials屬性或者在提取 API credentialsRequest()構造函數中的選項一塊兒工做。必須在雙方(Access-Control-Allow-Credentials的 header 和 XHR 或 Fetch 請求中)設置證書,以使 CORS 請求憑證成功。微信

Headers

Access-Control-Allow-Headers響應報頭在響應用於一個預檢請求指示哪一個HTTP標頭將經過提供Access-Control-Expose-Headers使實際的請求時。app

[糾錯](javascript:;)

簡單標頭AcceptAccept-LanguageContent-LanguageContent-Type(任一,但僅與一個MIME類型其解析值的(忽略參數)application/x-www-form-urlencodedmultipart/form-datatext/plain),老是可用的,而且不須要由該頭中列出。

若是請求具備標頭,則此標頭是必需的Access-Control-Request-Headers

Methods

Access-Control-Allow-Methods響應標頭指定響應訪問所述資源到時容許的一種或多種方法預檢請求

POST,GET,OPTIONS...

Origin

Access-Control-Allow-Origin響應 header 指示是否該響應能夠與具備給定資源共享原點

重點 Access-Control-Expose-Headers

Access-Control-Expose-Headers響應報頭指示哪些報頭能夠公開爲經過列出他們的名字的響應的一部分。

默認狀況下,只顯示6個簡單的響應標頭

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

若是您但願客戶端可以訪問其餘標題,則必須使用Access-Control-Expose-Headers標題列出它們。

首先爲何會出現 Options 請求 由於瀏覽器認爲你是跨域了,因此發起了一次請求.

首先理解一下Simple Request https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests

簡單請求,簡單請求受限,不會觸發Cors檢查,

容許的方法 必須在之內 不能超出,

Methods: GET POST HEAD

Headers:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type
  5. DRP
  6. Downlink
  7. Save-Data
  8. Viewport-Width
  9. With

developer.mozilla.org/en-US/docs/…

Content-Type 只容許如下內容

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain

可能咱們最多見的 是 OAuth2 時候會有一個 Authorizationheader

這就違反了Simple Request

因而 他就開始了他的預請求之路 Options

解決:

enable-cors.org/server.html

舉例 Tomcat

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
複製代碼

什麼? 你的是Springboot

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/** * @author 鄭查磊 * @date 2019-07-12 10:50 * @email <a href="mailto:stone981023@gmail.com">SmallStone</a> */
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8000")
                .allowedMethods("*")
                .allowedHeaders("*")
                .allowCredentials(true)
                .exposedHeaders("Authorization")
                .maxAge(1800 * 2 * 24 * 30 * 12);
    }

}
複製代碼

還有其餘的辦法, 你也能夠經過加攔截器

或者 @CrossOrigin

注意了 若是你是 Spring Security Oauth2

/** * @author 鄭查磊 * @date 2019年7月18日17:43:32 * https://stackoverflow.com/questions/37516755/spring-boot-rest-service-options-401-on-oauth-token */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {

    private FilterConfig config;

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) resp;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, resp);
        }

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        config = filterConfig;
    }
}

複製代碼

微信截圖_20190718180021.png

Options 只會看見一次 後面的由於 Access-Control-Max-Age: 3600 或者更大 在1小時內只會檢查一次 換個瀏覽器又會出現哦!

個人博客: runjava.cn

相關文章
相關標籤/搜索