实际工作中遇到了,在此做个笔记,希望能够帮助到遇到此问题的猿友们!!!
目录
3.设置Access-Control-Allow-Origin允许多域名访问
前端访问后端接口从页面控制台Network中看到接口报错,请求方法为OPTIONS,状态值为302;
页面控制台中报错:No 'Access-Control-Allow-Origin' header is present on the requested resource
此时作者后端代码为:
- 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);
-
- }
- }
- 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;
- }
-
- }
方式一:
-
- 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() {
-
- }
- }
例:前端工程部署时使用浏览器默认端口:80 。后端工程端口为 8080 。nginx 监听端口 8082 。
前端请求后端 URL 为:http:// nginx所在服务器 IP : 8082 。
前端工程请求 8082,nginx 收到请求再转发到实际服务,取得数据,并最终再返回。
(nginx 所在服务器也就是代理服务器,可以和后端服务器为同一主机)
在 nginx 配置文件中设置为:

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

注:这种方式允许所有域名都可以访问,并不安全,而且这种方式浏览器不能携带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() {
-
- }
- }
期待大家的三连击,你们的支持是我的动力。加油,猿友们!!