跨域请求问题

Posted guanxiying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跨域请求问题相关的知识,希望对你有一定的参考价值。

跨域请求

同源策略

什么是同源策略

同源策略是浏览器的安全策略,请求发过去,服务器返回了数据但是被浏览器拦截了

同源策略要求:请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同

CORS(跨域资源共享)

实现跨域资源共享的关键是服务器,只要服务器实现了CORS接口就可以跨域通信

CORS通信与同源的AJAX通信没有差别,代码完全一样,浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求

CORS基本流程

浏览器将CORS请求分成两类:简单请求(simple request)非简单请求(not-so-simple request)。
浏览器发出CORS简单请求只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

CORS两种请求详解

只要同时满足以下两大条件,就属于简单请求。

"""
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
"""

凡是不同时满足上面两个条件,就属于非简单请求。

浏览器对这两种请求的处理,是不一样的。

简单请求和非简单请求的区别

  • 简单请求:一次请求
  • 非简单请求:两次请求,在发送数据之前会先发一次OPTIONS请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
"""
- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
     => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
        Access-Control-Request-Method
     => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
        Access-Control-Request-Headers
"""

支持跨域,简单请求

服务器设置响应头:Access-Control-Allow-Origin = ‘域名’ 或 ‘*’

支持跨域,复杂请求

由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。

  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers

Django项目中支持CORS

返回的结果中加入允许信息(简单请求)

def test(request):
    import json
    obj=HttpResponse(json.dumps({‘name‘:‘lqz‘}))
    # obj[‘Access-Control-Allow-Origin‘]=‘*‘
    obj[‘Access-Control-Allow-Origin‘]=‘http://127.0.0.1:8004‘
    return obj

用中间件处理复杂请求和简单请求

from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
    def process_response(self,request,response):
        if request.method=="OPTIONS":
            #可以加*表示所有的请求都允许进来
            response["Access-Control-Allow-Headers"]="Content-Type"
        response["Access-Control-Allow-Origin"] = "http://localhost:8080"
        return response

使用第三方库django-cors-headers解决跨域问题

使用pip安装

pip install django-cors-headers

添加到settings的app中

INSTALLED_APPS = (
	...
	‘corsheaders‘,
	...
)

添加中间件

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
	...
	‘corsheaders.middleware.CorsMiddleware‘,
	‘django.middleware.common.CommonMiddleware‘,
	...
]

setting下面添加下面的配置

CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
	‘*‘
)
CORS_ALLOW_METHODS = (
	‘DELETE‘,
	‘GET‘,
	‘OPTIONS‘,
	‘PATCH‘,
	‘POST‘,
	‘PUT‘,
	‘VIEW‘,
)

CORS_ALLOW_HEADERS = (
	# ‘XMLHttpRequest‘,
	# ‘X_FILENAME‘,
	# ‘accept-encoding‘,
	‘authorization‘,
	‘content-type‘,
	# ‘dnt‘,
	# ‘origin‘,
	# ‘user-agent‘,
	# ‘x-csrftoken‘,
	# ‘x-requested-with‘,
	# ‘Pragma‘,
    # 额外允许的请求头
    # ‘token‘,
)

CORS、XSS、CSRF分别指啥

XSS:跨站脚本攻击

用户通过编写js代码存到数据库,前端页面渲染自动运行js

CORS:跨域资源共享

请求发出后,服务器接收到并且也返回了数据但是在浏览器中被拦截了,这是同源策略,跨域资源共享就是为了解决同源策略问题的,其通信的关键是服务器,只要服务器实现了CORS接口 就可以实现跨域通信,打通前后端进行数据交互

CSRF:跨站请求伪造

技术图片




以上是关于跨域请求问题的主要内容,如果未能解决你的问题,请参考以下文章

如何发送跨域ajax请求[重复]

跨域请求问题

JQuery - Ajax和Tomcat跨域请求问题解决方法!

SpringBoot 跨域请求处理

跨域问题

Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段