美文网首页
我和跨域的狗皮膏药故事

我和跨域的狗皮膏药故事

作者: 小石头_08aa | 来源:发表于2019-07-22 15:19 被阅读0次

    跨域

    谈谈跨域之前, 我们先谈谈这几个响应头.

    Access-Control-Allow-Credentials : true

    Access-Control-Allow-Headers : *

    Access-Control-Allow-Methods: *

    Access-Control-Allow-Origin: http://baidu.com

    redentials

    access-Control-Allow-Credentials响应报头指示的请求的响应是否可以暴露于该页面。当true值返回时它可以被暴露。

    凭证是 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使实际的请求时。

    [纠错](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

    https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests

    Content-Type 只允许以下内容

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

    可能我们最常见的 是 OAuth2 时候会有一个 Authorizationheader

    这就违反了Simple Request

    于是 他就开始了他的预请求之路 Options

    解决:

    https://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;
        }
    }
    
    

    Options 只会看见一次 后面的因为 Access-Control-Max-Age: 3600 或者更大
    在1小时内只会检查一次 换个浏览器又会出现哦!

    我的博客: https://runjava.cn

    相关文章

      网友评论

          本文标题:我和跨域的狗皮膏药故事

          本文链接:https://www.haomeiwen.com/subject/qerwlctx.html