1. 程式人生 > >網頁外鏈用了 target="_blank",結果悲劇了

網頁外鏈用了 target="_blank",結果悲劇了

今天給大家分享一個 Web 知識點。如果你有過一段時間的 Web 開發經驗,可能已經知道了。不過對於剛接觸的新手來說,還是有必要了解一下的。 我們知道,網頁裡的`a`標籤預設在當前視窗跳轉連結地址,如果需要在新視窗開啟,需要給 `a` 標籤新增一個`target="_blank"`屬性。 ``` 1024譯站 ``` 順便提下一個有意思的現象,很早之前我就發現,國外網站傾向於在當前頁跳轉,而國內網站喜歡開啟新視窗。不信你們可以去驗證下。我不知道這是互動設計上的文化差異,還是技術上的開發習慣。 當然,這兩種方式各有優缺點。當前頁跳轉顯得操作比較有連貫性,不會貿然打斷使用者的注意力,也會減少瀏覽器的視窗(tab 頁)數量。但是對於需要反覆回到初始頁面的場景來說,就很麻煩了。比如搜尋結果頁面,通常需要檢視對比幾個目標地址,保留在多個視窗還是比較方便。 今天要說的不只是使用者體驗上的差別,而是涉及安全和效能。 ### 安全隱患 如果只是加上`target="_blank"`,開啟新視窗後,新頁面能通過`window.opener`獲取到來源頁面的`window`物件,即使跨域也一樣。雖然跨域的頁面對於這個物件的屬性訪問有所限制,但還是有漏網之魚。 ![image.png](https://user-gold-cdn.xitu.io/2020/3/15/170dc349a51401f5?w=1240&h=400&f=png&s=157053) 這是某網頁開啟新視窗的頁面控制檯輸出結果。可以看到`window.opener`的一些屬性,某些屬性的訪問被攔截,是因為跨域安全策略的限制。 即便如此,還是給一些操作留下可乘之機。比如修改`window.opener.location`的值,指向另外一個地址。你想想看,剛剛還是在某個網站瀏覽,隨後打開了新視窗,結果這個新視窗神不知鬼不覺地把原來的網頁地址改了。這個可以用來做什麼?釣魚啊!等你回到那個釣魚頁面,已經偽裝成登入頁,你可能就稀裡糊塗把賬號密碼輸進去了。 ![](https://user-gold-cdn.xitu.io/2020/3/15/170dc358debbf39e?w=1000&h=600&f=jpeg&s=48145) 還有一種玩法,如果你處於登入狀態,有些操作可能只是傳送一個`GET`請求就完事了。通過修改地址,就執行了非你本意的操作,其實就是 CSRF 攻擊。 ### 效能問題 除了安全隱患外,還有可能造成效能問題。通過`target="_blank"`開啟的新視窗,跟原來的頁面視窗共用一個程序。如果這個新頁面執行了一大堆效能不好的 JavaScript 程式碼,佔用了大量系統資源,那你原來的頁面也會受到池魚之殃。 ### 解決方案 儘量不使用`target="_blank"`,如果一定要用,需要加上`rel="noopener"`或者`rel="noreferrer"`。這樣新視窗的`window.openner`就是`null`了,而且會讓新視窗執行在獨立的程序裡,不會拖累原來頁面的程序。當然,有些瀏覽器對效能做了優化,即使不加這個屬性,新視窗也會在獨立程序開啟。不過為了安全考慮,還是加上吧。 我特意用自己的部落格網站 [1024譯站](http://kaysonli.com/) 試了一下,點選裡面的外鏈開啟新頁面,`window.openner`都是`null`。檢視頁面元素髮現,`a`標籤都加上了` rel="noreferrer"`。部落格是用 Hexo 生成的,看來這種設定已經成了基本常識了。 另外,對於通過`window.open`的方式開啟的新頁面,可以這樣做: ``` var yourWindow = window.open(); yourWindow.opener = null; yourWindow.location = "http://someurl.here"; yourWindow.target = "_blank"; ``` 如果覺得本文對你有幫助,請關注下微信公眾號:1024譯站,這是對我最大的支援! ![微信公眾號:1024譯站](https://user-gold-cdn.xitu.io/2020/3/11/170c7474bf074ade?w=258&h=258&f=jpeg&