用golang实例来看看浏览器的同源策略

版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则会用法律维权。 https://blog.csdn.net/stpeace/article/details/82822382

         明天中秋节, 今天出来吃海底捞,取号后,还要等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)
    }
}

         用go run static.go跑起来, 然后在浏览器中访问:http://localhost:8080/static

         可以看到, 浏览器上显示了一个按钮。

         再看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跑起来。

        点击浏览器中的那个按钮, form表单触发去访问http://localhost:9999/hello

        然后,我们在页面上调试可以看到:

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.

        出现了很常见的拒绝问题, 为什么在http://localhost:8080/static对应的页面无法访问http://localhost:9999/hello呢?因为这受到了浏览器同源策略的限制(端口不一致了,非同源)    

        这里一定要注意一个问题,即使在浏览器页面调试中出现了如上错误, 也不能说明server.go对应的服务没有返回内容, 来抓包实际看看就知道了(如下是在服务端用tcpdump抓的包):

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, 不会出现上述错误了。

        好了, 基于上述实际例子, 再去理解同源策略的内容和原理吧。

        暂不多说, 以后再说。

        海底捞,还需要排队,人好多。

猜你喜欢

转载自blog.csdn.net/stpeace/article/details/82822382
今日推荐