解决前后端跨域问题No‘Access-Control-Allow-Origin‘...

2年前 (2022) 程序员胖胖胖虎阿
301 0 0

实际工作中遇到了,在此做个笔记,希望能够帮助到遇到此问题的猿友们!!!

目录

问题场景

​编辑此时作者后端代码为:

自定义过滤器:

WebMvcConfig配置文件: 注入自定义过滤器

解决方法

1.后端代码中设置解决跨域代码

2.使用Nginx进行解决跨域

 3.设置Access-Control-Allow-Origin允许多域名访问

方式一:设置允许多域名访问最简单的方法是使用通配符。

 方式二:使用数组过滤的方式 


问题场景

        前端访问后端接口从页面控制台Network中看到接口报错,请求方法为OPTIONS,状态值为302;

        页面控制台中报错:No 'Access-Control-Allow-Origin' header is present on the requested resource

解决前后端跨域问题No‘Access-Control-Allow-Origin‘...此时作者后端代码为:

 

自定义过滤器:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyFilterConfig implements Filter {

    private Logger logger= LoggerFactory.getLogger(getClass());

   @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        //*表示允许所有域名跨域
        httpResponse.setHeader("Access-Control-Allow-Origin","*");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        httpResponse.setHeader("Access-Control-Max-Age", "5000");
        httpResponse.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Authorization,Token");
        filterChain.doFilter(servletRequest, servletResponse);

    }
}

WebMvcConfig配置文件: 注入自定义过滤器

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Arrays;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Value("${file.fileMapPath}")
    private String fileMapPath;

    /**
     * 自定义过滤器,解决前后端分离跨域问题
     * @return
     */
    @Bean
    public FilterRegistrationBean myFilter(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        //传入自己创建的filter
        filterRegistrationBean.setFilter(new MyFilterConfig());
        //设置拦截路径
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        return filterRegistrationBean;
    }

}

解决方法

1.后端代码中设置解决跨域代码

方式一:


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyFilterConfig implements Filter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //*表示允许所有域名跨域
        logger.info("进入过滤器");
        String origin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", origin);
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "5000");
        response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Authorization, Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        String method = request.getMethod();
        if (method.equalsIgnoreCase("OPTIONS")) {
            servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
        } else {
            filterChain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {

    }
}

方式二:response.setHeader("Access-Control-Allow-Origin", "*");


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyFilterConfig implements Filter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //*表示允许所有域名跨域
        logger.info("进入过滤器");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "5000");
        response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Authorization, Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        String method = request.getMethod();
        if (method.equalsIgnoreCase("OPTIONS")) {
            servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
        } else {
            filterChain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {

    }
}

2.使用Nginx进行解决跨域

例:前端工程部署时使用浏览器默认端口:80 。后端工程端口为 8080 。nginx 监听端口 8082 。

前端请求后端 URL 为:http://  nginx所在服务器 IP : 8082 。

前端工程请求 8082,nginx 收到请求再转发到实际服务,取得数据,并最终再返回。
(nginx 所在服务器也就是代理服务器,可以和后端服务器为同一主机)

在 nginx 配置文件中设置为:

解决前后端跨域问题No‘Access-Control-Allow-Origin‘...

端口占用情况如下:红框是 nginx 、黄框是前端工程、蓝框是后端工程。

解决前后端跨域问题No‘Access-Control-Allow-Origin‘...

 3.设置Access-Control-Allow-Origin允许多域名访问

方式一:设置允许多域名访问最简单的方法是使用通配符。

注:这种方式允许所有域名都可以访问,并不安全,而且这种方式浏览器不能携带cookie信息(携带cookie信息只能使用真实域名,如下面第二中方式)。这种方式只推荐在不带cookie信息的开发中测试使用。

response.setHeader("Access-Control-Allow-Origin", "*");

 方式二:使用数组过滤的方式 


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class MyFilterConfig implements Filter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //*表示允许所有域名跨域
        logger.info("进入过滤器");
        // 设置允许多个域名请求
        String[] allowDomains = {"http://www.toheart.xin","http://192.168.11.213:8080","http://localhost:8080"};
        Set allowOrigins = new HashSet(Arrays.asList(allowDomains));
        String origin = request.getHeader("Origin");
        if(allowOrigins.contains(origin)){
            //设置允许跨域的配置
            // 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
            response.setHeader("Access-Control-Allow-Origin", origin);
        }
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "5000");
        response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Authorization, Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        String method = request.getMethod();
        if (method.equalsIgnoreCase("OPTIONS")) {
            servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
        } else {
            filterChain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {

    }
}

期待大家的三连击,你们的支持是我的动力。加油,猿友们!!

相关文章

暂无评论

暂无评论...