SpringBoot设置跨域的几种方式

    • 什么是跨域?

        浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域 

      原因:

        由于浏览器的同源策略, 即a网站只能访问a网站的内容,不能访问b网站的内容.

      注意:

        跨域问题只存在于浏览器,也就是说当你的前端页面访问后端简单请求的接口时,返回值是有的,只是服务器没有在请求头指定跨域的信息,所以浏览器自动把返回值给"屏蔽了".

        经过上面的了解,可以得出几个解决跨域的方法(不考虑前端实现):

        1.服务端指定跨域信息

        2.在web页面与服务器之间加一层服务指定跨域信息,比如nginx
       

      使用springboot提供了跨域的方法:

        1.5版本为继承WebMvcConfigurerAdapter 类实现抽象方法,

      //springboot 1.5方式
      @Configuration
      public class WebMvcConfig extends WebMvcConfigurerAdapter {
       
        @Override
        public void addCorsMappings(CorsRegistry registry) {
          registry.addMapping("/**").allowedHeaders("*")
            .allowedMethods("*")
            .allowedOrigins("*")
            .allowCredentials(true);
        }
      }

      2.0以后为实现WebMvcConfigurer 接口重写方法

      //springboot 2.0以上的方式
      @Configuration
      public class WebMvcConfig implements WebMvcConfigurer {
       
          @Override
          public void addCorsMappings(CorsRegistry registry) {
              registry.addMapping("/**")
                      .allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
                      .allowedMethods("*")
                      .allowedOrigins("*")
                      .allowCredentials(true);
          }
      }

      使用拦截器实现跨域:

      import org.springframework.context.annotation.Configuration;
      import org.springframework.web.servlet.HandlerInterceptor;
      import org.springframework.web.servlet.ModelAndView;
      import org.springframework.web.servlet.config.annotation.CorsRegistry;
      import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
      import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
       
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
       
      @Configuration
      public class WebMvcConfig implements WebMvcConfigurer {
          @Override
          public void addInterceptors(InterceptorRegistry registry) {
              registry.addInterceptor(new HandlerInterceptor() {
                  @Override
                  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                      response.addHeader("Access-Control-Allow-Origin", "*");
                      response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                      response.addHeader("Access-Control-Allow-Headers",
                              "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,token");
                      return true;
                  }
       
                  @Override
                  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       
                  }
       
                  @Override
                  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       
                  }
              });
          }
       
      }

      注意:

      请求头中自定义的字段是不允许跨域的,所以要指定

      response.addHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,token");

      或者

      response.addHeader("Access-Control-Allow-Headers", "*");

      还可以使用servlet提供的过滤器进行跨域配置:

      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Component;
      
      import javax.servlet.*;
      import javax.servlet.annotation.WebFilter;
      import javax.servlet.http.Cookie;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      import java.io.IOException;
      
      /**
       * 请求的基本过滤器 预处理请求头
       */
      @Component
      @WebFilter(urlPatterns = {"/*"}, filterName = "tokenAuthorFilter")
      public class TokenAuthorFilter implements Filter {
      
          private static Logger LOG = LoggerFactory.getLogger(TokenAuthorFilter.class);
      
          @Override
          public void destroy() {
      
          }
      
          @Override
          public void doFilter(ServletRequest request, ServletResponse response,
                               FilterChain chain) throws IOException, ServletException {
              HttpServletRequest req = (HttpServletRequest) request;
              HttpServletResponse rep = (HttpServletResponse) response;
      
              HttpSession session = req.getSession();
              LOG.info("sessionId:{}", session.getId());
              //LOG.info("Origin:{}", req.getHeader("Origin"));
      
              //设置允许跨域的配置
              // 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
              rep.setHeader("Access-Control-Allow-Origin", "*");
              //rep.setHeader("Access-Control-Allow-Origin", "*");
              rep.setHeader("Access-Control-Expose-Headers", jwtProperties.getHeader());
              // 允许的访问方法
              rep.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
              // Access-Control-Max-Age 用于 CORS 相关配置的缓存
              rep.setHeader("Access-Control-Max-Age", "3600");
              rep.setHeader("Access-Control-Allow-Headers", "token, Origin, X-Requested-With, Content-Type, Accept");
              //若要返回cookie、携带seesion等信息则将此项设置我true
              rep.setHeader("Access-Control-Allow-Credentials", "true");
              // 把获取的Session返回个前端Cookie
              //rep.addCookie(new Cookie("JSSESIONID", session.getId()));
              chain.doFilter(req, rep);
      
          }
      
          @Override
          public void init(FilterConfig arg0) throws ServletException {
      
          }
      
      }

      灵活的跨域方式:

        如果我们只想提供一个方法可以跨域,那么可以使用注解的形式:

      @CrossOrigin
      @RestController
      public class TestController {
      
      }
 

 

posted @ 2023-01-10 13:54  甜菜波波  阅读(5774)  评论(0编辑  收藏  举报