跨域限制訪問,即爲瀏覽器禁止訪問其他網站的資源,是瀏覽器的限制。如果缺少了同源策略,網頁很容易受到XSS、CSFR等攻擊。
同源策略是Web應用程序安全性模型中的重要概念。根據該策略,Web瀏覽器允許第一個網頁中包含的腳本訪問第二個網頁中的數據,但前提是兩個網頁具有相同的來源。來源由URI,主機名(hostname) 和端口號(port) 的組合定義。此策略可防止一個頁面上的惡意腳本通過該頁面的DOM(Document Object Model)獲得對另一網頁上敏感數據的訪問。
跨域場景
當一個請求 URL 的協議、域名、端口三者之間任意一個與當前頁面 URL 不同即爲跨域
當前頁面URL | 請求頁面URL | 是否跨域 | 原因 |
---|---|---|---|
http://www.test.com/ | http://www.test.com/index.html | 否 | 同源(協議、域名、端口號相同) |
http://www.test.com/ | https://www.test.com/index.html | 是 | 協議不同(http/https) |
http://www.test.com/ | http://www.baidu.com/ | 是 | 主域名不同(test/baidu) |
http://www.test.com/ | http://blog.test.com/ | 是 | 子域名不同(www/blog) |
http://www.test.com:8080/ | http://www.test.com:8081/ | 是 | 端口號不同 |
跨域解決方案
JSONP
由於同源策略,一般來說網頁無法跨域請求資源,而 HTML 的 <script>元素是一個例外。利用 <script>元素的這個開放策略,網頁可以得到從其他來源動態產生的JSON數據,而這種使用模式就是所謂的 JSONP。用JSONP抓到的數據並不是JSON,而是任意的JavaScript,用 JavaScript 解釋器運行而不是用 JSON 解析器解析。
JSONP優點是簡單兼容性好,可用於解決主流瀏覽器的跨域數據訪問的問題。缺點是僅支持 get 方法,具有侷限性;且可能會遭受 XSS 攻擊。
CORS
CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫。它是 W3C 標準,屬於跨源 AJAX 請求的根本解決方法。
Access-Control-Allow-Origin
設置允許請求的域名,多個域名以逗號分隔Access-Control-Allow-Methods
設置允許請求的方法,多個方法以逗號分隔Access-Control-Allow-Headers
設置允許請求自定義的請求頭字段,多個字段以逗號分隔Access-Control-Allow-Credentials
設置是否允許發送 Cookies
常用的跨域配置只需設置 Access-Control-Allow-Origin
,推薦設置爲對應域名。但當使用 Cookies 時,還需要配置Access-Control-Allow-Credentials
爲true
,且此時Access-Control-Allow-Origin
的配置不能爲*
,而必須配置爲具體的域名。
Java 跨域實現方案
JSONP
Spring 4 ~ Spring 5 低版本中支持全局Jsonp。在 Spring 5 高版本中棄用,且標註建議使用@CrossOrigin
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
/**
*
* 統一支持 jsonp 的配置輸出
* 使用說明:@RequestMapping 中指定 produces 爲 application/json;charset=UTF-8 即可
* 例子:@RequestMapping(path = "/signin", produces = "application/json;charset=UTF-8")
*
*/
@ControllerAdvice(basePackages = {"com.yy.ent.union.zone.controller"})
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback", "jsonpcb");
}
}
@CrossOrigin
使用@CrossOrigin
註解時,推薦指定域名,避免使用*
的默認配置,產生不安全的隱患
@RestController
@CrossOrigin(origins = "*")
public class TestController {}
當需要使用Cookies時,要配置allowCredentials
參數,使用時必須指定具體的域
@CrossOrigin(origins = "http://www.test.com/", allowCredentials = "true")
參考資料:
1.什麼是跨域?跨域解決方法