1. 程式人生 > >吃海底撈前用golang例項來看看瀏覽器的同源策略

吃海底撈前用golang例項來看看瀏覽器的同源策略

         明天中秋節, 今天出來吃海底撈,取號後,還要等100多桌,呵呵噠。索性來奈雪喝茶,寫點東西玩玩。

        瀏覽器同源策略? 網上一查一大堆,多數是理論講解,網文也經常到處複製抄襲, 我不具體解釋理論了。 本文來簡單玩一下, 便於對瀏覽器的同源策略有更具體地理解。

        來看static.go的程式碼:

package main
 
import (
    "io"
    "log"
    "net/http"
)

func staticFile(w http.ResponseWriter, r *http.Request) {
    str := `
        <html>
            <body>
                <div>
                    <input type="button" id="ok" value="click"/>
                </div>
            </body>
        </html>

        <script>
                var btn = document.getElementById('ok');
                btn.onclick = function()
                {
                    var xmlHttp = new XMLHttpRequest();
                    xmlHttp.open('post', 'http://localhost:9999/hello')
                    //xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded")
                    xmlHttp.send("key=123")
                    xmlHttp.onreadystatechange = function () 
                    {
                        if (xmlHttp.readyState == 4 && xmlHttp.status == 200) 
                        {
                            //alert("ok")
                        }
                    }
                }
        </script>
        `
    io.WriteString(w, str)
}

func main() {
    http.HandleFunc("/static", staticFile) 
    err := http.ListenAndServe("localhost:8080", nil)
    if err != nil {
        log.Println(err)
    }
}

         可以看到, 瀏覽器上顯示了一個按鈕。

         再看server.go的內容:

package main
 
import (
    "io"
    "log"
    "net/http"
)

func handlerHello(w http.ResponseWriter, r *http.Request) {
    str := "hello world"
    io.WriteString(w, str)
}
 
func main() {
    http.HandleFunc("/hello",  handlerHello) 
    err := http.ListenAndServe("localhost:9999", nil)
    if err != nil {
        log.Println(err)
    }
}

         用go run server.go跑起來。

        然後,我們在頁面上除錯可以看到:

Failed to load http://localhost:9999/hello: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

        這裡一定要注意一個問題,即使在瀏覽器頁面除錯中出現瞭如上錯誤, 也不能說明server.go對應的服務沒有返回內容, 來抓包實際看看就知道了:

HTTP/1.1 200 OK
Date: Sun, 23 Sep 2018 10:12:09 GMT
Content-Length: 11
Content-Type: text/plain; charset=utf-8

hello world

        可見, server.go對應的服務端還是返回了正確內容的!只是瀏覽器針對伺服器的回包,在渲染顯示的時候,做了同源限制而已。

       那怎麼處理這種限制呢? 我們可以在server.go程式碼中加上w.Header().Set("Access-Control-Allow-Origin", "*")就可以了, 具體如下:

package main
 
import (
    "io"
    "log"
    "net/http"
)

func handlerHello(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*") 
    
    str := "hello world"
    io.WriteString(w, str)
}
 
func main() {
    http.HandleFunc("/hello",  handlerHello) 
    err := http.ListenAndServe("localhost:9999", nil)
    if err != nil {
        log.Println(err)
    }
}

         OK, 不會出現上述錯誤了。

        好了, 基於上述實際例子, 再去理解同源策略的內容和原理吧。

        暫不多說, 以後再說。

        海底撈,還需要排隊,人好多。