美文网首页
彻底解决跨域问题

彻底解决跨域问题

作者: 夜色001 | 来源:发表于2020-04-19 14:03 被阅读0次

    跨域校验是浏览器的行为,旨在提升不同站点访问的安全性。在提升安全性的同时也增加了开发者的开发难度,为了解决跨域问题,开发者们想出了一些列解决方案,来允许跨域(更确切地说是在可控范围内允许跨域)。在前后端分离流行的今天,前端和后端都发展出了解决跨域的方法,本篇文章主要讲解后端的跨域解决方案。

    1、跨域问题本地测试

    在本地搭建前端、后端服务,用花生壳做内网穿透,前端接口调用指向穿透链接。即可模拟跨域场景,同时也可以在本地调试。【只要端口不同,不用做内网穿透也是可以重现跨域场景的】


    image.png

    2、服务端跨域解决方案

    新增filter,设置响应header的跨域参数。
    参数包括:
    Access-Control-Allow-Origin:允许跨域的请求发起源网站。不要粗暴的写成"*",要从请求头中获取origin,明确具体的来源。
    Access-Control-Allow-Credentials:允许客户端携带验证信息。若前端设置了withCredentials: true则此处必须设置为true。
    Access-Control-Allow-Methods:允许跨域的方法。GET\POST\PUT\DELETE
    Access-Control-Max-Age
    Access-Control-Allow-Headers

    在解决跨域问题时也要注意浏览器的提示,有的放矢,不要胡乱猜测,一通操作。

    The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '' when the request's credentials mode is 'include'.

    image.png
    检查Access-Control-Allow-Origin是否设置成
    ,改成具体的前端网址地址,或者((HttpServletRequest) servletRequest).getHeader("origin")即可。

    The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.


    image.png

    检查Access-Control-Allow-Credentials是否设置成true。

    3、复杂请求put和delete的跨域解决方案

    有些同学设置了跨域后,发现put和delete依然存在跨域,其原因是put和delete为复杂请求,复杂请求会先发起options请求,判断服务器是否支持后续的请求,所以不能简单的return,return前需要将put,delete等配置好跨域。见代码中的setHeader方法。

    4、代码

    随便找个目录放进去就可以了。

    package pro.haichuang.ktwelve.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    import java.io.IOException;
    
    import org.springframework.http.HttpStatus;
    import pro.haichuang.ktwelve.util.L;
    
    @Configuration
    @Order(value = 0)
    @WebFilter(filterName = "CorsFilterConfig", urlPatterns = "/*")
    public class CorsFilterConfig implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            L.i(new Throwable().getStackTrace()[0] + "===============CorsFilterConfig执行=================");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletResponse res = (HttpServletResponse) servletResponse;
            String origin = ((HttpServletRequest) servletRequest).getHeader("origin");
            res.setHeader("Access-Control-Allow-Origin", origin);
            res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
            res.setHeader("Access-Control-Allow-Credentials", "true");
            res.setHeader("Access-Control-Max-Age", "1728000");
            res.setHeader("Access-Control-Allow-Headers", "Authentication, Authorization, content-type, Accept, x-requested-with, Cache-Control");
            HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
            HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
    
            String requestMethod = httpRequest.getMethod();
            if (requestMethod.equals(RequestMethod.OPTIONS.name())) {
                setHeader(httpRequest, httpResponse);
                return;
            }
            filterChain.doFilter(servletRequest, res);
        }
    
        private void setHeader(HttpServletRequest request, HttpServletResponse response) {
            //跨域的header设置
            String origin = request.getHeader("origin");
            response.setHeader("Access-Control-Allow-Origin", origin);
            //这句可以解决当请求为put和delete时的跨域问题
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
            //防止乱码,适用于传输JSON数据
            response.setHeader("Content-Type", "application/json;charset=UTF-8");
            response.setStatus(HttpStatus.OK.value());
        }
    
        @Override
        public void destroy() {
        }
    }
    
    

    相关文章

      网友评论

          本文标题:彻底解决跨域问题

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