明天中秋节, 今天出来吃海底捞,取号后,还要等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, 不会出现上述错误了。
好了, 基于上述实际例子, 再去理解同源策略的内容和原理吧。
暂不多说, 以后再说。
海底捞,还需要排队,人好多。