跨域等问题

栏目: jQuery · 发布时间: 1年前

来源: blog.o1hy.com

内容简介:跨域相关的问题最近又把先用

本文转载自:https://blog.o1hy.com/2019/02/28/跨域等问题/,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

跨域相关的问题

环境配置

最近又把 xampp 换成了 wampserverwampserver 真好用!

先用 wampserver 配置两个 virtualhost

virtualhost

先在 httpd.conf 开启 virtualhost

然后配置 httpd-vhosts.conf

最后配置计算机中的 hosts 文件

httpd-vhosts.conf中的配置

<VirtualHost *:80>
	ServerName abc.test.com
	DocumentRoot "e:/code/**/www2"
	<Directory  "e:/code/**/www2/">
		Options +Indexes +Includes +FollowSymLinks +MultiViews
		AllowOverride All
		Require local
	</Directory>
</VirtualHost>

DocumentRoot“ **” #主站点的网页存储位置。

ServerName“ **” #主站点名称(网站的主机名)。

<directory> 是对目录进行访问控制的相关功能。

Options :配置在特定目录使用哪些特性,常用的值和基本含义如下:

  • ExecCGI: 在该目录下允许执行CGI脚本。
  • FollowSymLinks: 在该目录下允许文件系统使用符号连接。
  • Indexes : 当用户访问该目录时,如果用户找不到DirectoryIndex指定的主页文件(例如index.html),则返回该目录下的文件列表给用户。
  • includes :允许使用 mod_include 模块提供的 服务器 端包含功能。
  • MultiViews :如果客户端请求的路径可能对应多种类型的文件,那么服务器将根据客户端请求的具体情况自动选择一个最匹配客户端要求的文件。例如,在服务器站点的 file 文件夹下中存在名为 hello.jpghello.html 的两个文件,此时用户输入 Http://localhost/file/hello ,如果在 file 文件夹下并没有 hello 子目录,那么服务器将会尝试在 file 文件夹下查找形如 hello.* 的文件,然后根据用户请求的具体情况返回最匹配要求的 hello.jpg 或者 hello.html

AllowOverride:

  • None 不读取.htaccess
  • all 允许.htaccess所有指令,缺省是all

Require

  • local 仅允许本机访问
  • Require ip 192.168.1.104 192.168.1.205
  • Require host example.org

跨域问题

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)

无论是简单请求,还是非简单请求都会带来跨域问题,只是其他的一些不同。

简单请求

满足下面条件的是简单请求:

  • 请求方法是以下三种: HEAD , GET , POST
  • HTTP的头信息只含有以下这些字段: Accept , Accept-Language , Content-Language , Last-Event-ID , Content-Type 。其中 Content-Type 只允许三个值,分别为: application/x-www-form-urlencodedmultipart/form-datatext/plain

非简单请求

不满足简单请求的,即为非简单请求。

简单请求

看下面的代码,实现了一个简单的请求。

<!DOCTYPE html>
<html>
<head>
	<title>test2</title>
	<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
	<button id='button'>Ajax</button>
</body>
<script>
	$('#button').click(
		function(){
			$.ajax(
				{
					method: 'GET',
					url:"http://127.0.0.1:5000",
					headers: { 'Content-Type':'text/plain'},
					success:function(result){alert(result);},
					error: function(result) {console.log('error!');}
    			}
    		);
		}
	)
</script>
</html>

服务器代码

from flask import Flask, jsonify, request
app = Flask(__name__)

@app.route('/')
def hello_world():
    print('123')
    return 'Hello World!'

现在查看下结果。虽然这是个简单请求,但是仍然会引发跨域。

跨域等问题

现在我们查看下服务器的情况,虽然跨域了,但是服务器返回了结果,只是前端没有得到。

跨域等问题

再看一下请求包,服务器发送的是GET请求的信息。

简单请求,就自动在头信息之中,添加一个 Origin 字段

跨域等问题

看一下相应包,服务器其实返回了!

跨域等问题

总结

​ 也就是说,在发送简单请求时,服务器收到这个请求,是当作正常请求处理的,但是浏览器阻止了这一过程。所以这种情况下,就会存在安全的隐患。因为服务器是执行了代码的。

非简单请求

前端代码,在header中添加了 ‘others’ 请求头。后端代码未变。

<!DOCTYPE html>
<html>
<head>
	<title>test2</title>
	<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
	<button id='button'>Ajax</button>
</body>
<script>
	$('#button').click(
		function(){
			$.ajax(
				{
					method: 'GET',
					url:"http://127.0.0.1:5000",
					headers: { 'Content-Type':'text/plain','others':'1234'},
					success:function(result){alert(result);},
					error: function(result) {console.log('error');}
    			}
    		);
		}
	)
</script>
</html>

先看以下请求包,惊奇的发现,它变成了 opption

跨域等问题

看一下响应包,发现变成了空!

跨域等问题

再看一下后面的服务器,发现它只收到了 OPPTION 的请求,并且没有执行代码。

跨域等问题

解决跨域问题

那面对这两种情况,该如何处理呢。

简单请求

看一下图一中的报错, 已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:5000/ 的远程资源。(原因:CORS 头缺少 ‘Access-Control-Allow-Origin’) 。所以我们需要在服务器中,为它增加 Access-Control-Allow-Origin

服务器端代码如下:

@app.route('/')
def hello_world():
    resp = make_response(jsonify({'data': 'hello'}))  # 返回 json 格式
    resp.headers['Access-Control-Allow-Origin'] = "http://abc.test.com"
    return resp

对于简单请求,除了 Access-Control-Allow-Origin 字段外,还有另外两个需要关注的字段。

Access-Control-Allow-Credentials如果请求需要带cookie,该header必须为true,同时Access-Control-Allow-Origin不能为*,否则同样拿不到结果。一些问题看下文。

Access-Control-Allow-Methods:用于预检请求响应,表示允许使用的HTTP方法。

处理简单请求,常见的服务器代码。

resp.headers['Access-Control-Allow-Origin'] = "http://abc.test.com"
resp.headers['Access-Control-Allow-Credentials'] = 'true'
resp.headers['Access-Control-Allow-Methods'] = "POST, GET, OPTIONS, PUT, DELETE, PATCH"

非简单请求

客户端代码如下

$('#button').click(
		function(){
			$.ajax(
				{
					method: 'GET',
					url:"http://127.0.0.1:5000",
					headers: { 'Content-Type':'text/plain','others':'1234'},
					success:function(result){alert(result);},
					error: function(result) {console.log('error');}
    			}
    		);
		}
	)

需要服务器端跟前端协商好,服务器端对不符合简单请求的字段进行添加。这里主要 flask 有一个坑,它必须在路由方法中加上 OPTIONS 这个方法才能收到。

@app.route('/', methods=['POST', 'GET', 'OPTIONS'])  # 坑
def hello_world():
    print(request.cookies)
    resp = make_response(jsonify({'data': 'hello'}))
    resp.headers['Access-Control-Allow-Origin'] = "*"
    resp.headers['Access-Control-Allow-Methods'] = "POST, GET, OPTIONS, PUT"
    resp.headers['Access-Control-Allow-Headers'] = "others, content-type"
    return resp

跨域请求过程中的cookie

我在尝试 Access-Control-Allow-Credentials 字段时,遇到了一些问题。两种不同程度的跨域,问题如下图。

跨域等问题

首先,对于 ajax 跨域,在 jquery 的ajax中,是禁止直接在header头,添加cookie的,需要通过如下方式。它的前端代码如下:

function(){
			$.ajax(
					{
						method: 'GET',
						url:"http://127.0.0.1:5000",
						xhrFields: {
					            withCredentials: true
					        },
						success:function(result){alert(result);},
						error: function(result) {console.log('error');}
	    			}
    			);
    		}

而对于图中的问题,经过查阅资料以及测试发现,只有二者属于同一个域(域名)下,才能跨域携带cookie。

对于第二种情况,如果想让 abc.test.com 携带cookie,必须先由服务器进行 set-cookie 。然后客户端才能携带cookie。但是服务器 setcookie ,客户端是无法获取,无法更改的。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

关注码农网公众号

关注我们,获取更多IT资讯^_^


查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序设计语言

程序设计语言

斯科特 / 裘宗燕 / 电子工业出版社 / 2005-1 / 88.00元

这是一本很有特色的教材,其核心是讨论程序设计语言的工作原理和技术。本书融合了传统的程序设计语言教科书和编译教科书的有关知识,并增加了一些有关汇编层体系结构的材料,以满足没学过计算机组织的学生们的需要。书中通过各种语言的例子,阐释了程序设计语言的重要基础概念,讨论了各种概念之间的关系,解释了语言中许多结构的形成和发展过程,以及它们演化为今天这种形式的根源。书中还详细讨论了编译器的工作方式和工作过程,......一起来看看 《程序设计语言》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具