資安

Spring Boot 使用CORS處理跨域問題——《我的Java打怪日記》

為什麼會出現跨域問題?

根本原因是同源策略問題,同源策略是由Netscape提出的一個著名的安全策略,它是瀏覽器最核心也最基本的安全功能,現在所有支持JavaScript的瀏覽器都會使用這個策略。

同源

同源是指,域名,協議,端口相同。

跨域

域名,協議,端口有一個不一樣都是跨域,簡單的解釋一下,,你從你從端口號為8000去請求8001的數據就是跨域.
如果想解決跨域問題,需要瀏覽器同時支持。

什麼是CORS

CORS是一個W3C標準,全稱是”跨域資源共享”(Cross-origin resource sharing),允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
它通過服務器增加一個特殊的Header[Access-Control-Allow-Origin]來告訴客戶端跨域的限制,如果瀏覽器支持CORS、並且判斷Origin通過的話,就會允許XMLHttpRequest發起跨域請求。

Request Headers(請求頭)

Origin
表示跨域請求的原始域。
Access-Control-Request-Method
表示跨域請求的方式。(如GET/POST)
Access-Control-Request-Headers
表示跨域請求的請求頭信息。

Response headers(響應頭 )

Access-Control-Allow-Origin
表示允許哪些原始域進行跨域訪問。(字符數組)
Access-Control-Allow-Credentials
表示是否允許客戶端獲取用戶憑據。(布爾類型)
使用場景:例如現在從瀏覽器發起跨域請求,並且要附帶Cookie信息給服務器。則必須具備兩個條件:1. 瀏覽器端:發送AJAX請求前需設置通信對象XHR的withCredentials 屬性為true。 2.服務器端:設置Access-Control-Allow-Credentials為true。兩個條件缺一不可,否則即使服務器同意發送Cookie,瀏覽器也無法獲取。
Access-Control-Allow-Methods
表示跨域請求的方式的允許範圍。(例如只授權GET/POST)
Access-Control-Allow-Headers
表示跨域請求的頭部的允許範圍。
Access-Control-Expose-Headers
表示暴露哪些頭部信息,並提供給客戶端。(因為基於安全考慮,如果沒有設置額外的暴露,跨域的通信對象XMLHttpRequest只能獲取標準的頭部信息)
Access-Control-Max-Age

Spring Boot 如何處理跨域問題

方式一:直接使用@CrossOrigin註解

這是最簡單,也是控制力度最小的一種方式,可以直接在Controller上添加註解,也可以在某一個方法上添加註解,這樣你就可控制某個方法/某個Controller支持跨域,這樣更安全。

@RestController
@RequestMapping(method = {RequestMethod.POST,RequestMethod.GET},value = "test")
@Slf4j
@CrossOrigin
public class TestController {

  @RequestMapping("/test")
  @ApiOperation("綁卡接口")
  public void test(){
  }
}

方式二:使用Configuration

增加一個配置類,CORSConfiguration.java,實現WebMvcConfigurer接口,重寫addCorsMappings(CorsRegistry registry)

@Configuration
public class CORSConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods( "GET", "POST", "PUT", "DELETE").maxAge(3600);
    }
}

方法三:採用過濾器(filter)

增加一個CordFilter類,實現Filter接口,並在方式二的配置類中增加corsFilter方法

public class CorsFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setStatus(HttpStatus.OK.value());
            return;
        }
        chain.doFilter(req, res);
    }
}
@Configuration
public class CORSConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods( "GET", "POST", "PUT", "DELETE").maxAge(3600);
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *