跳转至

Django使用django-cors-headers处理API跨域问题

问题说明

在Django开发过程中,使用前后端分离设计的站点越来越多,如Django+VUE、Django+Angular。在使用DjangoRestFramework开发API的过程中,由于前端站点和后端API站点域名往往不同,随之而来的便是跨域问题。

跨域攻击是一种常见的Web攻击手段,常见的攻击流程为: 假设现在你有一个前端站点A和后端站点B,前端站点A使用Ajax的GET请求后端站点B的接口/withdraw/?money=1000&account=yinkh可以向账号yinkh提现一千元,整个过程使用token认证或者session认证,用户的身份信息会被缓存在用户的浏览器中。现在假设有不法分子架设了一个站点C,在站点C中放入一张图片其src路径设置为/withdraw/?money=1000&account=xxxx,不法分子再将站点C的链接通过一定的方式诱导你在缓存有后端站点B的浏览器中访问,如果后端站点B没有做跨域访问控制的话,你就将像不法分子的账户xxxx提现一千元。

而跨域访问控制是通过验证请求来源站点,以防止跨域攻击。只有你将前端站点A对应的域名添加至后端站点B的可信列表中,你才能正确的请求对应的API接口,否则请求将被后端站点B拒绝。

安装

pip install django-cors-headers==2.4.0

设置

settings.py中:

1 设置 INSTALLED_APPS

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]

2 设置 MIDDLEWARE,若你使用的Django版本小于1.10,该项为MIDDLEWARE_CLASSES。

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

3 设置信任站点

# 允许跨域
if DEBUG:
    CORS_ORIGIN_ALLOW_ALL = True
else:
    CORS_ORIGIN_WHITELIST = (
        'www.example.com',
    )

需要注意的是,在生产环境中既DEBUG=True时,不可以直接将 CORS_ORIGIN_ALLOW_ALL 设置为 True,这项设置相当于关闭了站点防止跨域攻击的功能。在生产环境中需要使用CORS_ORIGIN_WHITELIST,将你信任的前端站点域名加入CORS_ORIGIN_WHITELIST列表中,该域名不要以http://或者https://开头。

至此你的前端站点应该就可以正确的访问后端站点的接口了。

更多设置项请参见文档

笔记

Q: 在使用了django-cors-headers库后,无法获取自定义的requset header

A: settings.py加入:

from corsheaders.defaults import default_headers
# The list of non-standard HTTP headers that can be used when making the actual request
CORS_ALLOW_HEADERS = default_headers + ('YourCustomHeaderName',)