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


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

    目录

    问题场景

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

    自定义过滤器:

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

    解决方法

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

    2.使用Nginx进行解决跨域

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

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

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


    问题场景

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

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

    此时作者后端代码为:

     

    自定义过滤器:

    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import javax.servlet.*;
    4. import javax.servlet.http.HttpServletResponse;
    5. import java.io.IOException;
    6. public class MyFilterConfig implements Filter {
    7. private Logger logger= LoggerFactory.getLogger(getClass());
    8. @Override
    9. public void init(FilterConfig filterConfig) throws ServletException {
    10. logger.info("过滤器初始化");
    11. }
    12. @Override
    13. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    14. HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
    15. //*表示允许所有域名跨域
    16. httpResponse.setHeader("Access-Control-Allow-Origin","*");
    17. httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
    18. httpResponse.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    19. httpResponse.setHeader("Access-Control-Max-Age", "5000");
    20. 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");
    21. filterChain.doFilter(servletRequest, servletResponse);
    22. }
    23. }

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

    1. import org.springframework.beans.factory.annotation.Value;
    2. import org.springframework.boot.web.servlet.FilterRegistrationBean;
    3. import org.springframework.context.annotation.Bean;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    7. import java.util.Arrays;
    8. @Configuration
    9. public class MvcConfig implements WebMvcConfigurer {
    10. @Value("${file.fileMapPath}")
    11. private String fileMapPath;
    12. /**
    13. * 自定义过滤器,解决前后端分离跨域问题
    14. * @return
    15. */
    16. @Bean
    17. public FilterRegistrationBean myFilter(){
    18. FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    19. //传入自己创建的filter
    20. filterRegistrationBean.setFilter(new MyFilterConfig());
    21. //设置拦截路径
    22. filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
    23. return filterRegistrationBean;
    24. }
    25. }

    解决方法

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

    方式一:

    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import javax.servlet.*;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpServletResponse;
    6. import java.io.IOException;
    7. public class MyFilterConfig implements Filter {
    8. private Logger logger = LoggerFactory.getLogger(getClass());
    9. @Override
    10. public void init(FilterConfig filterConfig) throws ServletException {
    11. logger.info("过滤器初始化");
    12. }
    13. @Override
    14. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    15. HttpServletResponse response = (HttpServletResponse) servletResponse;
    16. HttpServletRequest request = (HttpServletRequest) servletRequest;
    17. //*表示允许所有域名跨域
    18. logger.info("进入过滤器");
    19. String origin = request.getHeader("Origin");
    20. response.setHeader("Access-Control-Allow-Origin", origin);
    21. response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    22. response.setHeader("Access-Control-Max-Age", "5000");
    23. 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");
    24. response.setHeader("Access-Control-Allow-Credentials", "true");
    25. String method = request.getMethod();
    26. if (method.equalsIgnoreCase("OPTIONS")) {
    27. servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
    28. } else {
    29. filterChain.doFilter(request, response);
    30. }
    31. }
    32. @Override
    33. public void destroy() {
    34. }
    35. }

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

    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import javax.servlet.*;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpServletResponse;
    6. import java.io.IOException;
    7. public class MyFilterConfig implements Filter {
    8. private Logger logger = LoggerFactory.getLogger(getClass());
    9. @Override
    10. public void init(FilterConfig filterConfig) throws ServletException {
    11. logger.info("过滤器初始化");
    12. }
    13. @Override
    14. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    15. HttpServletResponse response = (HttpServletResponse) servletResponse;
    16. HttpServletRequest request = (HttpServletRequest) servletRequest;
    17. //*表示允许所有域名跨域
    18. logger.info("进入过滤器");
    19. response.setHeader("Access-Control-Allow-Origin", "*");
    20. response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    21. response.setHeader("Access-Control-Max-Age", "5000");
    22. 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");
    23. response.setHeader("Access-Control-Allow-Credentials", "true");
    24. String method = request.getMethod();
    25. if (method.equalsIgnoreCase("OPTIONS")) {
    26. servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
    27. } else {
    28. filterChain.doFilter(request, response);
    29. }
    30. }
    31. @Override
    32. public void destroy() {
    33. }
    34. }

    2.使用Nginx进行解决跨域

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

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

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

    在 nginx 配置文件中设置为:

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

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

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

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

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

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

    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import javax.servlet.*;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpServletResponse;
    6. import java.io.IOException;
    7. import java.util.Arrays;
    8. import java.util.HashSet;
    9. import java.util.Set;
    10. public class MyFilterConfig implements Filter {
    11. private Logger logger = LoggerFactory.getLogger(getClass());
    12. @Override
    13. public void init(FilterConfig filterConfig) throws ServletException {
    14. logger.info("过滤器初始化");
    15. }
    16. @Override
    17. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    18. HttpServletResponse response = (HttpServletResponse) servletResponse;
    19. HttpServletRequest request = (HttpServletRequest) servletRequest;
    20. //*表示允许所有域名跨域
    21. logger.info("进入过滤器");
    22. // 设置允许多个域名请求
    23. String[] allowDomains = {"http://www.toheart.xin","http://192.168.11.213:8080","http://localhost:8080"};
    24. Set allowOrigins = new HashSet(Arrays.asList(allowDomains));
    25. String origin = request.getHeader("Origin");
    26. if(allowOrigins.contains(origin)){
    27. //设置允许跨域的配置
    28. // 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
    29. response.setHeader("Access-Control-Allow-Origin", origin);
    30. }
    31. response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    32. response.setHeader("Access-Control-Max-Age", "5000");
    33. 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");
    34. response.setHeader("Access-Control-Allow-Credentials", "true");
    35. String method = request.getMethod();
    36. if (method.equalsIgnoreCase("OPTIONS")) {
    37. servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
    38. } else {
    39. filterChain.doFilter(request, response);
    40. }
    41. }
    42. @Override
    43. public void destroy() {
    44. }
    45. }

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

  • 相关阅读:
    【012】wireshark抓包分析libpq和postmaster之间的通信
    WebShell后门检测与WebShell箱子反杀
    JVM原理学习笔记总结
    Azure AD Domain Service(二)为域服务中的机器配置 Azure File Share 磁盘共享
    C笔记:引用调用,通过指针传递
    leetcode 1222. 可以攻击国王的皇后(每日一题)
    图像信号处理板设计原理图:2-基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板
    浅谈结构化数据、非结构化数据,关系数据库、非关系数据库
    手把手教你打造美观实用的家居微信小程序
    手撕各种排序
  • 原文地址:https://blog.csdn.net/weixin_43552143/article/details/125414510