Apache与Nginx虚拟机的三种访问+非简单请求+跨域知识点整理

news/2024/11/27 23:43:24/

Apache

在D:\project\web\index.html中写入

<h1>welcome useing apache!</h1>

基于ip访问
打开phpstudy_pro\Extensions\Apache2.4.39\conf\extra\httpd-vhosts.conf写入

<VirtualHost 192.168.1.4:80>ServerAdmin 88888888@163.com #管理员邮箱DocumentRoot "D:\project\web" #网站根目录ServerName www.index.com #域名ServerName	www.index666.com #网站别名ErrorLog "logs/dummy-host2.example.com-error.log" #错误日志	CustomLog "logs/dummy-host2.example.com-access.log" common	#访问日志
</VirtualHost>

在这里插入图片描述
基于域名访问
在httpd.conf里取消注释
在这里插入图片描述

httpd-vhosts.conf文件内写入

<VirtualHost *:80>#增加站点DocumentRoot "D:\project\web"#增加主机名ServerName "www.index.com"<Directory "D:\project\web">#允许所有请求Require all granted#重写不生效AllowOverride None#不启用任何服务器特性Options None</Directory>
</VirtualHost>

在windows主机的C:\Windows\System32\drivers\etc\hosts文件写入

127.0.0.1 www.index.com
<?php phpinfo();

站点目录写入php文件
在这里插入图片描述
在这里插入图片描述
基于端口访问
在listen.conf中添加81端口
在这里插入图片描述

httpd-vhosts.conf文件内写入

<VirtualHost 192.168.175.128:81>DocumentRoot "D:\project\web"ServerName www.index.com
</VirtualHost>

在这里插入图片描述

ngninx

基于端口

vim /etc/nginx/conf.d/server.confserver{listen 81;server_name localhost;location /{root /var/www/nginx/server; #指定网页访问的目录index index.html index.htm; #指定访问的主页}
}

创建网页文件

mkdir -p /var/www/nginx/server
vim /var/www/nginx/server/index.html

在这里插入图片描述

nginx -t #检查nginx运行配置是否正确
systemctl restart nginx #重启nginx服务

在这里插入图片描述
基于域名
修改windows下的hosts文件这里Windows主机和Linux主机一定要能相互ping通
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

vim /etc/nginx/conf.d/server.conf server{listen 80;server_name www.ikun.com;location /{root /var/www/nginx/server;index index.html index.htm;}
}

测试时关闭防火墙

systemctl stop firewalld.service 

在这里插入图片描述
基于ip
添加一个网卡
在这里插入图片描述

vim /etc/nginx/conf.d/server.conf server{listen 80;server_name 192.168.150.129;location /{root /var/www/nginx/server;index index.html index.htm;}
}

测试时关闭防火墙

systemctl stop firewalld.service 

在这里插入图片描述

非简单请求

非简单请求
常见的情况有 Content-Type 为 application/json 的请求。浏览器在发出非简单请求前,会发送一次 options 请求。用于先询问服务器,当前域名是否被允许访问,以及可以使用哪些 methods 和 headers。只有服务器做出肯定的响应,浏览器才会发出正式的请求,否则就会报错。

options 请求的请求头会带上三个头

Origin 当前请求域名,必须
Access-Control-Request-Method 必须,用来列出正式请求的 method,例如 POST
Access-Control-Request-Headers 多个值用逗号隔开,例如 Content-Type
options 响应的响应头

Access-Control-Allow-Origin 必须,和简单请求一样
Access-Control-Allow-Credentials 可选,和简单请求一样
Access-Control-Max-Age 可选,用来指定本次 options 请求的有效期。单位为秒,在有效期内,不用发出另一条预检请求。
Access-Control-Allow-Methods 必须,多个 method 用逗号隔开,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的方法。这是为了避免多次预检请求。
Access-Control-Allow-Headers 如果浏览器请求头里包括 Access-Control-Request-Headers 字段,则 Access-Control-Allow-Headers 字段是必需的。多个值用逗号隔开,表明服务器支持的所有头信息字段,不限于浏览器在预检中请求的字段
然后返回 http 状态码 204

跨域知识点整理

那就是浏览器的“同源策略”(即协议相同,域名相同,端口相同)。如果非同源,共有三种行为会受到限制:
(1) Cookie,LocalStorage和IndexdDB无法读取
(2) DOM无法获得
(3) AJAX请求不能发送

Cookie
Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。我们可以在cookie中设置domain的值为一级域名,这样一级域名相同,二级域名不同的网页也可以共享cookie。

iframe
如果两个网页不同源,就无法拿到对方的DOM。对于完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题。

  • 片段标识符
  • window.name
  • 跨文档通信API
  • 片段标识符
    片段标识符(fragment identifier)指的是,URL的#号后面的部分,比如http://example.com/x.html#fragment的#fragment。如果只是改变片段标识符,页面不会重新刷新。

父窗口可以把信息,写入子窗口的片段标识符。

var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;

子窗口通过监听hashchange事件得到通知。

window.onhashchange = checkMessage;function checkMessage() {var message = window.location.hash;// ...
}

同样的,子窗口也可以改变父窗口的片段标识符。
window.name
浏览器窗口有window.name属性。这个属性最大的特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页就可以读取它。比如说,一个网页中包含一个iframe,我们把它的window.name设置为我们想访问的内部数据。这样在该网页中就能通过document.getElementById(‘myFrame’).contentWindow.name来访问它了。
这种方法的优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。

  • Window.postMessage
    HTML5引入了一个全新的API:跨文档通信API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口,不论这两个窗口是否同源。这个功能的实现包括接受信息的“message”事件和发送消息的“postMessage”方法。
    语法:
otherWindow.postMessage(message, targetOrigin);

otherWindow指目标窗口,也就是给哪个window发消息,是window.frames的成员或者由window.open方法创建的窗口。
参数说明:
message:是要发送的消息,类型为 String、Object (IE8、9 不支持)
targetOrigin: 是限定消息接收范围,不限制请使用 ‘*’

var onmessage = function (event) {var data = event.data;var origin = event.origin;//do someing};if (typeof window.addEventListener != 'undefined') {window.addEventListener('message', onmessage, false);} else if (typeof window.attachEvent != 'undefined') {//for iewindow.attachEvent('onmessage', onmessage);}

回调函数第一个参数接收 Event 对象,有三个常用属性:

data:  消息
origin:  消息来源地址
source:  源 DOMWindow 对象

例一:使用iframe创建子窗口

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>window.postMessage</title>
</head>
<body>
<iframe src="subFrame.html" id="myFrame" frameborder="0"></iframe><script>
var iframe = document.getElementById('myFrame').contentWindow;
setInterval(function () {iframe.postMessage('Hello', '*');
}, 6000);var onmessage = function (event) {var data = event.data;var origin = event.origin;console.log(data);console.log(origin);};if (typeof window.addEventListener != 'undefined') {window.addEventListener('message', onmessage, false);} else if (typeof window.attachEvent != 'undefined') {//for iewindow.attachEvent('onmessage', onmessage);}
</script>
</body>
</html>

例二:使用window.open打开窗口

<!--父窗口-->
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>window.postMessage</title>
</head>
<body>
<script>var popup = window.open('subFrame.html');setInterval(function () {popup.postMessage('Hello World', '*');},6000);var onmessage = function (event) {var data = event.data;var origin = event.origin;console.log(data);console.log(origin);};if (typeof window.addEventListener != 'undefined') {window.addEventListener('message', onmessage, false);} else if (typeof window.attachEvent != 'undefined') {//for iewindow.attachEvent('onmessage', onmessage);}
</script>
</body>
</html>
<!--子窗口-->
<!doctype html>
<html lang="en">
<head><title>subFrame</title>
</head>
<body><script>
window.opener.postMessage('nice to see you', '*');var onmessage = function (event) {var data = event.data;var origin = event.origin;console.log(data);console.log(origin);
};
if (typeof window.addEventListener != 'undefined') {window.addEventListener('message', onmessage, false);
} else if (typeof window.attachEvent != 'undefined') {//for iewindow.attachEvent('onmessage', onmessage);
}
</script>
</body>
</html>

通过window.postMessage,读写其他窗口的 LocalStorage 也成为了可能。

AJAX
同源政策规定,AJAX请求只能发给同源的网址,否则就报错。以下四种方法可以规避这个限制:
1.JSONP
2.CORS
3.WebSocket
JSONP
JSONP即JSON with padding,它有两部分组成,回调函数和数据。它的基本思想是,网页通过添加一个

<!DOCTYPE html>
<html>
<head><title>JSONP Example</title>
</head>
<body><script>function handleResponse(response){alert("You're at IP address " + response.ip + ", which is in " + response.city + ", " + response.region_name);}var script = document.createElement("script");script.src = "http://freegeoip.net/json/?callback=handleResponse";document.body.insertBefore(script, document.body.firstChild);</script>
</body>
</html>

CORS
一、简介
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

二、两种请求
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。

(1) 请求方法是以下三种方法之一:HEADGETPOST(2)HTTP的头信息不超出以下几种字段:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不同时满足上面两个条件,就属于非简单请求。
浏览器对这两种请求的处理,是不一样的。
三、简单请求
3.1 基本流程
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
下面是一个例子,浏览器发现这次跨源AJAX请求是简单请求,就自动在头信息之中,添加一个Origin字段。

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

上面的头信息之中,有三个与CORS请求相关的字段,都以Access-Control-开头。

(1)Access-Control-Allow-Origin

该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

(2)Access-Control-Allow-Credentials

该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

(3)Access-Control-Expose-Headers

该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。

3.2 withCredentials 属性

上面说到,CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。

Access-Control-Allow-Credentials: true

另一方面,开发者必须在AJAX请求中打开withCredentials属性。

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

否则,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。
但是,如果省略withCredentials设置,有的浏览器还是会一起发送Cookie。这时,可以显式关闭withCredentials。

xhr.withCredentials = false;

需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。
WebSocket
WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

下面是一个例子,浏览器发出的WebSocket请求的头信息。

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

上面代码中,有一个字段是Origin,表示该请求的请求源(origin),即发自哪个域名。

正是因为有了Origin这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。如果该域名在白名单内,服务器就会做出如下回应。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

发送数据,因为WebScoket只能通过连接发送纯文本数据,所以对于复杂的数据结构在发送之前必须进行序列化。
socket.send(JSON.stringfy(data));
接收数据:
socket.onmessage = function(event){};
关闭连接:
socket.close()


http://www.ppmy.cn/news/10932.html

相关文章

【Linux】进程信号万字详解(上)

&#x1f387;Linux&#xff1a; 博客主页&#xff1a;一起去看日落吗分享博主的在Linux中学习到的知识和遇到的问题博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 看似不起波澜的日复一日&#xff0c;一定会在某一天让你看见坚持…

若依分离版解决单个账号多设备登录问题

若依分离版解决单个账号多设备登录问题 1.application.yml添加相关配置&#xff0c;用于灵活控制单个账号多设备登录的情况 #token配置 token: # 这个是若依框架本身存在的配置 # 是否允许并多设备登录 true:允许 false:不允许 这个是新增的配置singleLogin: false2.Cach…

测试开发 | 跨平台设备管理方案 Selenium Grid

Selenium Grid 是 Selenium 的三大组件之一&#xff0c;它可以在多台机器上并行运行测试&#xff0c;集中管理不同的浏览器版本和浏览器配置。通过将客户端命令发送到远程浏览器的实例, Selenium Grid 允许在远程计算机 (虚拟或真实) 上执行 WebDriver 脚本. 它旨在提供一种在多…

【Python】python深拷贝和浅拷贝(二)

【Python】python深拷贝和浅拷贝&#xff08;二&#xff09; 前言 上一期我们介绍了Python中深拷贝和浅拷贝的定义以及它们在执行过程中内存结构&#xff0c;同时也给出了深拷贝和浅拷贝的方法。&#xff08;没有看上一期的朋友看这里&#xff0c;python深拷贝和浅拷贝&#…

基于javascript专题一总结(2023年版)

目录 函数柯里化 定义 #实现 #应用场景 #参数复用 Nodejs的EventEmitter #Api #基本使用 #手动实现EventEmitter #JavaScript自定义事件 防抖 浅拷贝和深拷贝 数组去重&#xff0c;扁平&#xff0c;最值 去重 #Object #indexOf filter #Set #排序 #去除重复…

canvas入门教学(5)运动小球屏保特效与下雪特效渲染

本节我们来学习两个例子,第一个例子是如下图这样的,全屏各色各样的小球随机运动,碰撞到屏幕边缘再反弹回来的特效,我们一步一步带着大家来学习这个canvas应用。 首先呢,基于上一个教程的例子,我们需要基础的构建圆, 上节教程在这里 并且呢我们要重复的多次的构建半径…

Vue技术教程(2023-1-9)

第一章&#xff1a;Vue概述 1.hello World Vue&#xff1a;易学易用 性能出色 适用场景丰富的web前端框架vue是一款构建用户界面的JavaScript框架 它基于标准的html css JavaScript构建 并提供了一种声明式 组件化的编程模型 帮助你高效的开发 用户界面 无论是简单还是复杂的…

第三十篇:稳定性容量规划方法

前言在谈容量规划之前&#xff0c;首先要知道我们的系统处理能力有限的&#xff0c;不可能是无限的&#xff0c;处理能力的限制取决于资源的限制&#xff0c;生活中很多这种例子&#xff0c;例如喝水的水杯&#xff0c;也是有容量限制的&#xff0c;超出容量限制&#xff0c;则…