CORS(Cross-Origin Resource Sharing) 跨域資源共享 瀏覽器在訪問當前域名下的資源時,能直接傳輸數據。可是出於安全考慮,瀏覽器在訪問非當前域名的資源時會遇到跨域訪問限制 這時候咱們須要一種機制:跨域資源共享(cors)
來自 CORS簡介(做者 loveis715)javascript
若是一個請求沒有包含任何自定義請求頭,並且它所使用HTTP動詞是GET,HEAD或POST之一,那麼它就是一個Simple Request。可是在使用POST做爲請求的動詞時,該請求的Content-Type須要是application/x-www-form-urlencoded,multipart/form-data或text/plain之一。
若是一個請求包含了任何自定義請求頭,或者它所使用的HTTP動詞是GET,HEAD或POST以外的任何一個動詞,那麼它就是一個Preflighted Request。若是POST請求的Content-Type並非application/x-www-form-urlencoded,multipart/form-data或text/plain之一,那麼其也是Preflighted Request。
通常狀況下,一個跨域請求不會包含當前頁面的用戶憑證。一旦一個跨域請求包含了當前頁面的用戶憑證,那麼其就屬於Requests with Credential。
springboot提供api服務(端口8080),前端經過jquery發送http請求(端口63342),因爲端口不一樣,會形成跨域訪問
springboot接口css
@GetMapping("/api/cors/get") public String get(){ return "cors test get method"; } @PostMapping("/api/cors/post") public String post(){ return "cors test post method"; }
前端代碼:cors.htmlhtml
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>cors跨域測試</title> <script src="https://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script> <script type="text/javascript"> function crosGet(){ $.ajax({ type:'get', url:'http://localhost:8080/api/cors/get', dateType: 'json', data:{}, success: function (data) { $("#getRes").html('請求成功。' + data); }, error: function (data) { console.log('請求失敗:' + data); $("#getRes").html('請求失敗!!!' + JSON.stringify(data)); } }); } function crosPost(){ $.ajax({ type:'post', url:'http://localhost:8080/api/cors/post', dateType: 'json', data:{}, success: function (data) { $("#postRes").html('請求成功。' + data); }, error: function (data) { $("#postRes").html('請求失敗!!!' + JSON.stringify(data)); } }); } </script> </head> <body> <button onclick="crosGet()">get跨域測試</button> <div id="getRes" style="width:80%;height:50px;background-color:#ccc;"></div> <hr/> <button onclick="crosPost()">post跨域測試</button> <div id="postRes" style="width:80%;height:50px;background-color:#ccc;"></div> </body> </html>
前端代碼cors.html能夠放到tomcat或者nginx中,這裏直接使用idea的open in Browser
打開,默認端口爲63342前端
啓動sprinboot後,點擊前端按鈕測試,會返回錯誤:java
Access to XMLHttpRequest at 'http://localhost:8080/api/cors/get' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. 當前域名:http://localhost:63342 要訪問的域名:http://localhost:8080 錯誤緣由:發生了跨域訪問,服務端(8080)未容許該域名(63342)進行訪問
springboot中,添加cors支持的配置:jquery
@Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://localhost:63342");//容許域名訪問,若是*,表明全部域名 } }; } }
再次測試,成功nginx
修改配置,只容許header中帶Authorization
或者Token
的請求訪問git
@Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedHeaders("Authorization", "Token")//容許的頭信息 .allowedOrigins("http://localhost:63342"); } }; } }
修改html中,post接口header帶Authorization
,get接口header帶aaa
ajax
function crosGet(){ $.ajax({ type:'get', url:'http://localhost:8080/api/cors/get', dateType: 'json', data:{}, headers:{'aaa':'Basic 123456'}, success: function (data) { $("#getRes").html('請求成功。' + data); }, error: function (data) { console.log('請求失敗:' + data); $("#getRes").html('請求失敗!!!' + JSON.stringify(data)); } }); } function crosPost(){ $.ajax({ type:'post', url:'http://localhost:8080/api/cors/post', dateType: 'json', data:{}, //headers:{'Authorization':'Basic 123456'},//帶頭信息方式1 beforeSend: function (xhr) { xhr.setRequestHeader('Authorization','Basic 123456');//帶頭信息方式2 }, success: function (data) { $("#postRes").html('請求成功。' + data); }, error: function (data) { console.log('請求失敗:' + data); $("#postRes").html('請求失敗!!!' + JSON.stringify(data)); } }); }
測試,get訪問失敗,post成功spring
修改配置,只支持post方式訪問:
@Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedHeaders("Authorization", "Token") .allowedMethods("POST")//只容許post方式 .allowedOrigins("http://localhost:63342"); } }; } }
測試,get訪問失敗,post成功
配置get和post都容許,則都訪問成功
egistry.addMapping("/api/**") .allowedMethods("GET", "POST")
上面是配置了全局的跨域訪問,也能夠配置局部訪問控制
類上面註解@CrossOrigin
@CrossOrigin(origins = "http://domain.com", allowedHeaders = "token", methods = {RequestMethod.GET, RequestMethod.POST}) @RestController public class TestResource{ }
方法上面的@CrossOrigin
@RestController public class TestResource{ @CrossOrigin(origins = "http://domain.com", allowedHeaders = {"header1", "header2"}) @GetMapping("/api/test") public String test(){ return "test"; } }