同源策略:判斷是不是同源的,主要看這三點,協議,ip,端口。html
同源策略就是瀏覽器出於網站安全性的考慮,限制不一樣源之間的資源相互訪問的一種政策。前端
好比在域名https://www.baidu.com下,腳本不可以訪問https://www.sina.com源下的資源,不然將會被瀏覽器攔截。jquery
注意兩點:git
1.必須是腳本請求,好比AJAX請求。github
可是以下狀況不會產生跨域攔截web
<img src="xxx"/> <a href='xxx"> </a>
2.跨域攔截是前端請求已經發出,而且在後端返回響應時檢查相關參數,是否容許接收後端請求。後端
在微服務開發中,一個系統包含多個微服務,會存在跨域請求的場景。跨域
本文主要講解SpringBoot解決跨域請求攔截的問題。瀏覽器
這裏建立兩個web項目,web1 和 web2.安全
web2項目請求web1項目的資源。
這裏只貼關鍵代碼,完整代碼參考GitHub
建立一個Controller返回html頁面
@Slf4j @Controller public class HomeController { @RequestMapping("/index") public String home(){ log.info("/index"); return "/home"; } }
html頁面 home.html
這裏建立了一個按鈕,按鈕按下則請求資源:"http://localhost:8301/hello"
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>web2</title> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"> </script> <script> $(function () { $("#testBtn").click(function () { console.log("testbtn ..."); $.get("http://localhost:8301/hello",function(data,status){ alert("數據: " + data + "\n狀態: " + status); }); }) }) </script> </head> <body> web2 <button id="testBtn">測試</button> </body> </html>
@Slf4j @RestController public class Web1Controller { @RequestMapping("/hello") public String hello(){ log.info("hello "); return "hello," + new Date().toString(); } }
這裏配置兩個項目爲不一樣的端口。
WEB1爲8301
WEB2爲8302
所以是不一樣源的。
在web1尚未配置容許跨域訪問的狀況下
按下按鈕,將會出現錯誤。顯示Header中沒有Access-Control-Allow-Origin
Access to XMLHttpRequest at 'http://localhost:8301/hello' from origin 'http://localhost:8300' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
WEB1添加容許跨域請求,經過實現WebMvcConfigurer
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/hello"); } }
再次訪問將會返回正常數據。
除了以上的配置外,還能夠作更細緻的限制
好比對請求的headers,請求的方法POST/GET...。請求的源進行限制。
同時還可使用註解 @CrossOrigin來替換上面的配置。
@Slf4j @RestController public class Web1Controller { @CrossOrigin @RequestMapping("/hello") public String hello(){ log.info("hello "); return "hello," + new Date().toString(); } }
註解能夠用在類上,也能夠用在方法上,但必須是控制器類
配置和上面同樣,也是能夠對方法,header,源進行個性化限制。
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CrossOrigin { /** @deprecated */ @Deprecated String[] DEFAULT_ORIGINS = new String[]{"*"}; /** @deprecated */ @Deprecated String[] DEFAULT_ALLOWED_HEADERS = new String[]{"*"}; /** @deprecated */ @Deprecated boolean DEFAULT_ALLOW_CREDENTIALS = false; /** @deprecated */ @Deprecated long DEFAULT_MAX_AGE = 1800L; @AliasFor("origins") String[] value() default {}; @AliasFor("value") String[] origins() default {}; String[] allowedHeaders() default {}; String[] exposedHeaders() default {}; RequestMethod[] methods() default {}; String allowCredentials() default ""; long maxAge() default -1L; }