谈谈跨域以前, 咱们先谈谈这几个响应头.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