詳解springboot解決CORS跨域的三種方式
一、實(shí)現(xiàn)WebMvcConfigurer接口
@Configuration public class WebConfig implements WebMvcConfigurer { /** * 添加跨域支持 */ @Override public void addCorsMappings(CorsRegistry registry) { // 允許跨域訪問(wèn)的路徑 '/**'表示應(yīng)用的所有方法 registry.addMapping("/**") // 允許跨域訪問(wèn)的來(lái)源 '*'表示所有域名來(lái)源 .allowedOriginPatterns("*") // .allowedOrigins("*") // 允許跨域訪問(wèn)的來(lái)源 SpringBoot2.4.0之前的版本 // 允許跨域請(qǐng)求的方法 '*'表示所有 .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") // 是否允許發(fā)送cookie true-允許 false-不允許 默認(rèn)false。對(duì)服務(wù)器有特殊要求的請(qǐng)求,比如請(qǐng)求方法是PUT或DELETE,或者Content-Type字段的類型是application/json,這個(gè)值只能設(shè)為true .allowCredentials(true) // 預(yù)檢間隔時(shí)間1小時(shí),單位為秒。指定本次預(yù)檢請(qǐng)求的有效期,在有效期間,不用發(fā)出另一條預(yù)檢請(qǐng)求。 // 瀏覽器發(fā)出CORS簡(jiǎn)單請(qǐng)求,只需要在頭信息之中增加一個(gè)Origin字段 // 瀏覽器發(fā)出CORS非簡(jiǎn)單請(qǐng)求,會(huì)在正式通信之前,增加一次OPTIONS查詢請(qǐng)求,稱為"預(yù)檢"請(qǐng)求(preflight)。瀏覽器先詢問(wèn)服務(wù)器,當(dāng)前網(wǎng)頁(yè)所在的域名是否在服務(wù)器的許可名單之中,以及可以使用哪些HTTP動(dòng)詞和頭信息字段。只有得到肯定答復(fù),瀏覽器才會(huì)發(fā)出正式的XMLHttpRequest請(qǐng)求,否則就報(bào)錯(cuò)。 .maxAge(3600) // 允許跨域請(qǐng)求可攜帶的header,'*'表所有header頭。CORS請(qǐng)求時(shí),XMLHttpRequest對(duì)象的getResponseHeader()方法只能拿到6個(gè)基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定 .allowedHeaders("*"); } }
二、實(shí)現(xiàn)filter過(guò)濾器方式
@WebFilter @Configuration public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); chain.doFilter(req, res); } }
三、注解@CrossOrigin
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
@CrossOrigin可配置在方法上,也可配置在類上。
四、實(shí)戰(zhàn)
創(chuàng)建兩個(gè)普通的SpringBoot項(xiàng)目A、B,A配置8081端口,B配置8082端口。
在A的resources/static目錄下創(chuàng)建一個(gè)html文件index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <!-- jquery庫(kù)可百度jquery cdn --> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> <script> function btnClick() { $.get('http://localhost:8082/hello/hello', function (msg) { $("#app").html(msg); }); } function btnClick2() { $.post('http://localhost:8082/hello/hello', function (msg) { $("#app").html(msg); }); } </script> <body> <div id="app"></div> <input type="button" onclick="btnClick()" value="get_button"> <input type="button" onclick="btnClick2()" value="post_button"> </body> </html>
B提供2個(gè)web接口:
@RestController @RequestMapping("/hello") public class HelloController { // @CrossOrigin(originPatterns = "*", allowCredentials = "true") @GetMapping("/hello") public String hello() { System.out.println("get hello"); return "get hello"; } // @CrossOrigin(originPatterns = "*", allowCredentials = "true") @PostMapping("/hello") public String hello2() { System.out.println("post hello"); return "post hello"; } }
分別啟動(dòng)A、B服務(wù),瀏覽器訪問(wèn)A的index.html,點(diǎn)擊按鈕,瀏覽器控制臺(tái)報(bào)錯(cuò)如下:http://localhost:8081/index.html
Access to XMLHttpRequest at 'http://localhost:8082/hello/hello' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
為B項(xiàng)目使用方式一,添加跨域支持,重啟,再次點(diǎn)擊按鈕,可正常訪問(wèn),觀察響應(yīng)頭多了支持跨域的信息:
五、cookie的跨域
從Chrome51開(kāi)始,瀏覽器cookie添加了一個(gè)新屬性SameSite,以防止 CSRF 攻擊和用戶跟蹤。
SameSite可取值:Strict、Lax、None。
Strict最為嚴(yán)格,完全禁止第三方 Cookie,跨站點(diǎn)時(shí),任何情況下都不會(huì)發(fā)送 Cookie。換言之,只有當(dāng)前網(wǎng)頁(yè)的 URL 與請(qǐng)求目標(biāo)一致,才會(huì)帶上 Cookie。
Lax規(guī)則稍稍放寬,大多數(shù)情況也是不發(fā)送第三方 Cookie,但是導(dǎo)航到目標(biāo)網(wǎng)址的 Get 請(qǐng)求除外。導(dǎo)航到目標(biāo) URL 的 GET 請(qǐng)求僅包括三種情況:鏈接、預(yù)加載請(qǐng)求和 GET 表單。
網(wǎng)站可以選擇顯式關(guān)閉SameSite屬性,將其設(shè)為None。不過(guò),前提是必須同時(shí)設(shè)置Secure屬性(Cookie 只能通過(guò) HTTPS 協(xié)議發(fā)送),否則無(wú)效。
SpringBoot 2.6及以上版本
網(wǎng)上查到可使用配置(但親測(cè)無(wú)效?。?/p>
server.servlet.session.cookie.same-site=none server.servlet.session.cookie.secure=true
SpringBoot 2.6以下版本
如果使用 Tomcat 作為服務(wù)器,則可以通過(guò)以下配置設(shè)置會(huì)話 cookie 的 SameSite 屬性(親測(cè)無(wú)效!)。
server.servlet.session.cookie.secure=true
@Configuration public class TomcatCookieConfig { @Bean public TomcatContextCustomizer sameSiteCookiesConfig() { return context -> { final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor(); // SameSite cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue()); context.setCookieProcessor(cookieProcessor); }; } }
如果您使用的是 Spring-Session,那么您可以使用以下配置來(lái)設(shè)置 cookie 的 SameSite 屬性。
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-core</artifactId> </dependency>
@Configuration public class SpringSessionConfiguration { @Bean public CookieSerializer cookieSerializer() { DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); // Strict-嚴(yán)格模式 Lax-松懈模式 None-無(wú) cookieSerializer.setSameSite("None"); cookieSerializer.setUseSecureCookie(true); return cookieSerializer; } }
自己的解決方式
@Configuration public class CookieConfig { private static String domain; @Value("${domain}") public void setDomain(String domain) { CookieConfig.domain = domain; } public static HttpCookie generateHttpCookie(String name, String value) { return ResponseCookie.from(name, value) .domain(domain) // cookie跨域設(shè)置 .sameSite("None") // 在https下傳輸,配合sameSite=None使用 .secure(true) .path("/") // 有效期24小時(shí) .maxAge(60 * 60 * 24) .build(); } }
@GetMapping("/hello") public String hello(HttpServletResponse response) { HttpCookie cookie2 = CookieConfig.generateHttpCookie("age", "18"); response.addHeader(HttpHeaders.SET_COOKIE, cookie2.toString()); HttpCookie cookie3 = CookieConfig.generateHttpCookie("id", "77"); response.addHeader(HttpHeaders.SET_COOKIE, cookie3.toString()); System.out.println("get hello"); return "get hello"; }
參考:https://www.cnblogs.com/javastack/p/14255114.html
到此這篇關(guān)于詳解springboot解決CORS跨域的三種方式的文章就介紹到這了,更多相關(guān)springboot CORS跨域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
不使用他人jar包情況下優(yōu)雅的進(jìn)行dubbo調(diào)用詳解
這篇文章主要為大家介紹了不使用他人jar包情況下優(yōu)雅的進(jìn)行dubbo調(diào)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09基于SpringBoot中activeMq的JmsTemplate的實(shí)例
這篇文章主要介紹了基于SpringBoot中activeMq的JmsTemplate的實(shí)例問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Java中的PrintWriter 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
PrintWriter 是字符類型的打印輸出流,它繼承于Writer。接下來(lái)通過(guò)本文給大家介紹java中的 PrintWriter 相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧2017-05-05SpringMVC通過(guò)注解獲得參數(shù)的實(shí)例
下面小編就為大家?guī)?lái)一篇SpringMVC通過(guò)注解獲得參數(shù)的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08Ubuntu安裝JDK與IntelliJ?IDEA的詳細(xì)過(guò)程
APT是Linux系統(tǒng)上的包管理工具,能自動(dòng)解決軟件包依賴關(guān)系并從遠(yuǎn)程存儲(chǔ)庫(kù)中獲取安裝軟件包,這篇文章主要介紹了Ubuntu安裝JDK與IntelliJ?IDEA的過(guò)程,需要的朋友可以參考下2023-08-08springboot寶塔簡(jiǎn)單部署的實(shí)現(xiàn)示例
通過(guò)使用Spring Boot,可以快速構(gòu)建出高效、可擴(kuò)展的應(yīng)用程序,而寶塔面板則提供了簡(jiǎn)單易用的網(wǎng)站管理和維護(hù)工具,本文將詳細(xì)介紹如何將Spring Boot應(yīng)用程序與寶塔面板進(jìn)行集成,實(shí)現(xiàn)自動(dòng)化部署、配置管理等操作2023-11-11Java實(shí)體類實(shí)現(xiàn)鏈?zhǔn)讲僮鲗?shí)例解析
這篇文章主要介紹了Java實(shí)體類實(shí)現(xiàn)鏈?zhǔn)讲僮鲗?shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12SpringBoot簡(jiǎn)單實(shí)現(xiàn)文件上傳
這篇文章主要介紹了SpringBoot簡(jiǎn)單實(shí)現(xiàn)文件上傳,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-09-09