Javascript跨域访问资源

本文介绍了解决Django开发的API在浏览器中遇到的跨域问题,详细解释了同源策略的概念,并介绍了如何使用CORS机制及Django中间件实现跨域资源共享。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    用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

### 解决资源共享 (CORS) 的 JavaScript 实现 当涉及到不同源之间的资源请求时,现代浏览器实施了严格的同源策略来保护用户的安全。为了绕过这些限制并合法地获取其他名上的数据,可以采用多种方式,其中最常用的是通过配置服务器端支持 CORS 来实现。 #### 利用 `fetch` API 进行简单的 GET 请求 对于不需要携带身份验证信息(如 cookie 或 HTTP 认证)的情况,可以直接利用 Fetch API 向目标 URL 发送 GET 请求: ```javascript fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error)); ``` 此代码片段展示了如何发起一个异步的网络调用来检索远程服务的数据,并将其解析为 JSON 对象以便进一步处理[^5]。 #### 设置带有凭证的请求 如果应用程序需要向另一个站点发送包含认证信息(例如 cookies)的请求,则必须确保客户端和服务端都正确设置了相应的头部参数。具体来说,在创建 XMLHttpRequest 对象实例之后,应该将 `withCredentials` 属性设为 true;与此同时,响应中也应当返回合适的 `Access-Control-Allow-Origin` 和 `Access-Control-Allow-Credentials` 字段值: ```javascript var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://example.com/api/resource'); xhr.withCredentials = true; xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) { console.log(JSON.parse(xhr.responseText)); } }; xhr.send(); ``` 需要注意的是,当启用了 credentials 支持后,`Access-Control-Allow-Origin` 不再能被设置成通配符 "*" ,而应指定具体的 URI 地址[^2]。 #### Spring Boot 中的处理 在某些情况下,可能希望简化开发流程并通过框架内置的功能自动管理 CORS 行为。以 Java 开发为例,Spring Boot 提供了一种便捷的方式来全局启用或针对特定控制器/路径定制化 CORS 策略。这通常涉及定义 @CrossOrigin 注解或者编写 WebMvcConfigurer 接口的具体实现类[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值