Javascript跨域访问资源

22 篇文章 1 订阅
10 篇文章 0 订阅
    用Django开发的API,在浏览器里可以正常访问,但在javascript里用GET访问,却报错如下:
    No 'Access-Control-Allow-Origin' header is present on the requested resource.

    查了一下,其实这个问题水还不浅,下面来分析一下。


    首先得知道,浏览器规定了一个“同源策略”(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(JS)在没明确授权的情况下,不能读写对方的资源。这是Netscape提出的一个著名的安全策略,所有能跑JS的浏览器都遵守这个策略[1]。
    就是说脚本只能向加载它的站点发送HTTP请求。浏览器能GET到(直接在浏览器地址栏里访问)的资源,脚本不一定能GET到。举个例子,比如通过这个URL(http://tb2.bdstatic.com/tb/static-spage/widget/member_rank/member_rank_z_a0f387f.pnG),可以访问到百度的一张图片。你把这个URL用浏览器直接访问,或者写在HTML的image元素的src里,都是可以正常访问到这张图片。但用JS来GET,就会报错。

    注意这个策略是浏览器策略,如果在其它非浏览器运行的脚本中,比如python,还是能GET到百度这个图片的。


    这个策略是一个安全策略,没有它,就会发生cookie劫持(A站点获取B站点的cookie)一类的安全问题。但这个策略规定的那么死,A站点的JS又不能调用B开发的API,那API就没啥用了。如果一个站点不能访问另一站点的资源,互联网上的资源冗余得有多大!


    所以,为了不让咱们白开发API,出现了CORS(跨域资源共享)。CORS是一种机制,只要服务器遵守这种机制,就能实现A站点的脚本访问B站点的资源,上面那个百度的图片就能被我们本地的JS脚本GET到了。
    CORS机制规定,服务器要在HTTP头中添加Access-Control-Allow-Origin, Access-Control-Allow-Methods,来限制其他站点和可以访问资源的方法。再看看最初提到的那个报错,不就是服务器没有配置Access-Control-Allow-Origin么。
    将支持CORS的站点地址添加到源服务器Access-Control-Allow-Origin,则该站点的JS,就能访问到源服务器中的资源。

    回到Django,利用Django的中间件,有更简单的方法能满足CORS机制,详见这里

1. 在Django项目的跟目录(manage.py所在目录)下
pip install django-cors-headers

2. 在settings.py中配置CORS_ORIGIN_ALLOW_ALL,则允许所有站点来访问资源
INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
)

CORS_ORIGIN_ALLOW_ALL = True  

    开放了所有站点来访问资源,在HTTP头中,Access-Control-Allow-Origin被设置为"*"。 允许所有站点访问资源的做法并不安全,比如黑客写一段无穷个GET来访问资源的代码,就可能导致服务器瘫痪,所以还可以设置白名单:

CORS_ORIGIN_WHITELIST = (
        'localhost:8083',
        'hostname.example.com'
    )


下面是Baidu在处理POST请求时的HTTP响应,它将Access-Control-Allow-Origin被设置为"*",看来Baidu还用了其它手段保证安全。


Ref:
[1]http://www.jianshu.com/p/4e17445d66e2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值