用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)
    }
}

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

 

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

        暂不多说, 以后再说。

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

 

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值