談談跨域以前, 咱們先談談這幾個響應頭.javascript
Access-Control-Allow-Credentials : truehtml
Access-Control-Allow-Headers : *java
Access-Control-Allow-Methods: *web
Access-Control-Allow-Origin: baidu.comspring
access-Control-Allow-Credentials
響應報頭指示的請求的響應是否能夠暴露於該頁面。當true
值返回時它能夠被暴露。apache憑證是 Cookie ,受權標頭或 TLS 客戶端證書。跨域
看成爲對預檢請求的響應的一部分使用時,它指示是否可使用憑證進行實際請求。請注意,簡單的
GET
請求不是預檢的,因此若是請求使用憑證的資源,若是此資源不與資源一塊兒返回,瀏覽器將忽略該響應,而且不會返回到 Web 內容。瀏覽器
Access-Control-Allow-Credentials
的 header 文件與該XMLHttpRequest.withCredentials
屬性或者在提取 APIcredentials
的Request()
構造函數中的選項一塊兒工做。必須在雙方(Access-Control-Allow-Credentials
的 header 和 XHR 或 Fetch 請求中)設置證書,以使 CORS 請求憑證成功。微信
Access-Control-Allow-Headers
響應報頭在響應用於一個預檢請求指示哪一個HTTP標頭將經過提供Access-Control-Expose-Headers
使實際的請求時。app[糾錯](javascript:;)
的簡單標頭,
Accept
,Accept-Language
,Content-Language
,Content-Type
(任一,但僅與一個MIME類型其解析值的(忽略參數)application/x-www-form-urlencoded
,multipart/form-data
或text/plain
),老是可用的,而且不須要由該頭中列出。若是請求具備標頭,則此標頭是必需的
Access-Control-Request-Headers
。
Access-Control-Allow-Methods
響應標頭指定響應訪問所述資源到時容許的一種或多種方法預檢請求。POST,GET,OPTIONS...
Access-Control-Allow-Origin響應 header 指示是否該響應能夠與具備給定資源共享原點。
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:
- Accept
- Accept-Language
- Content-Language
- Content-Type
- DRP
- Downlink
- Save-Data
- Viewport-Width
- With
developer.mozilla.org/en-US/docs/…
Content-Type 只容許如下內容
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
可能咱們最多見的 是 OAuth2 時候會有一個 Authorization
在header
中
這就違反了Simple Request
因而 他就開始了他的預請求之路 Options
解決:
舉例 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;
}
}
複製代碼
Options 只會看見一次 後面的由於 Access-Control-Max-Age: 3600 或者更大 在1小時內只會檢查一次 換個瀏覽器又會出現哦!
個人博客: runjava.cn