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 {

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM