什么是跨域访问?
由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一个与当前页面地址不同即为跨域。存在跨域的情况:
-
网络协议不同,如http协议访问https协议。
-
端口不同,如80端口访问8080端口。
-
域名不同,如qianduanblog.com访问baidu.com。
-
子域名不同,如abc.qianduanblog.com访问def.qianduanblog.com。
-
域名和域名对应ip,如www.a.com访问20.205.28.90.
-
请求的数据是XHR(XMLHttpRequest)浏览器会有跨域的限制。如果不是XHR类型的则不会限制
我们的浏览器需要禁止跨域呢?
这里举两个常见的例子:
1.我们知道一帮浏览器都使用cookie去储存我们的用户登录信息。如果允许跨域访问,那么别的网站只需要一段脚本就可以获取你的cookie,从而冒充你的身份去登录网站,造成非常大的安全问题。
2.假设现在有两个不同域,如果没有这一安全策略,那么当用户在访问a.com时,a.com的一段脚本就可以在不加载b.com的页面而随意修改或者获取b.com上面的内容。这样将会导致b.com页面的页面发生混乱。
跨域的解决办法
其实跨域的解决办法从本质上去区分,可以划分为两类。
第一类:被调用方
第二类:调用方
接下来我们就开始基于这两种类型去解决跨域问题。
被调用方的解决办法
这里在说明代码之前,我们要先知道在我们的请求中可以分为两种请求:(1)简单请求(2)非简单请求
简单请求:
在heard里面无定义头
Content-Type为一下几种:
text/plain
multipart/from-data
application/x-www-form-urlencoded
常见非简单请求:
put,delete方法的ajax请求
发送json格式的ajax请求
带自定义头的ajax请求
简单请求与非简单请求的区别
简单请求:浏览器会先自行后判断
非简单请求:浏览器先判断后执行(OPTIONS)
因此我们在访问非简单请求的时候,我们可以看到发送的方法会是opttions。意思就是服务器先询问服务是否存在相关资源。当存在相关资源的时候才能正常返回。
接下来我们就可以开展被调用方的解决方案:
解决方案1:JSONP
什么是JSONP?
Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
下面我们展示JSONP的使用案例
#这里我们模仿ajax进行一个跨越访问,其datatype需要设置为jsonp
#里面的jsonp,设置回调函数的名称为callback
<script type="text/javascript">
$.ajax({
url:"http://crossdomain.com/services.php",
dataType:'jsonp',
data:'',
jsonp:'callback',
success:function(result) {
for(var i in result) {
alert(i+":"+result[i]);//循环输出a:1,b:2,etc.
}
},
timeout:3000
});
</script>
#这是后台返回数据的方法
#可以看出其实就是把返回的数据再包含在与前端的回调函数的名字一样的函数体即可
function api_jsonp_encode($json) {
if (!empty($_GET['callbak'])) {
return $_GET['callbak'] . '(' . $json . ')'; // jsonp
}
return $json; // json
}
jsonp其实作为一种跨域的解决手段其实存在比较明显的缺陷:
1.服务器需要改动代码
2.只支持get方法
3.发送的不是XHR
解决方法2:增加header头
设置头文件:
//设置请求域名
header('Access-Control-Allow-Origin:*');
//设置请求头
header("Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Authorization");
//设置请求方法
header('Access-Control-Allow-Methods:GET, POST, PUT,DELETE,OPTIONS,PATCH');
header('Access-Control-Allow-Methods:*');
//设置预检命令的缓存头
header('Access-Control-Max-Age:3600');
#这里说明一下,*号代表没有限制全匹配。因此你可以看到们设置的请求域名,还有请求方法都是有*号配置。
#设置御检命令缓存头就是让浏览器当发送一次御检命令后,后期就可以在缓存时间内直接使用缓存,而不需要再次请求。其第二个参数为缓存时间
但是我们直接上述的配置,只能满足一般情况。因为如果当跨域访问的时候携带cookie,或者自定义头的时候我们还是不能成功跨域的因此。针对这两种情况,我们可以做出以下的调整修改
带Cookie的跨域
//设置允许携带Cookie
header("Access-Control-Allow-Credentials: true");
//需要设置与服务器匹配的域名,不能使用*
header('Access-Control-Allow-Origin:http://www.xxx.com');
#如果可能需要匹配多个允许域名,可以参考下面的动图做法
//通过系统变量获取origin
$origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';
//设置允许数组列表
$allow_origin = array(
'http://client1.runoob.com',
'http://client2.runoob.com'
);
//判断是否存在于数组中
if(in_array($origin, $allow_origin)){
header('Access-Control-Allow-Origin:'.$origin);
}
自定义请求头的跨域处理
一般情况下可以使用以下的代码设置请求头
header("Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Authorization");
但是如果不生效。可以把对应的请求头也写进去例如:
header("Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Authorization,test-header");
以上就是通过被调用方设置header头去解决对应的跨域问题。
但是上述的方法还是存在一定的局限性。因为加header头本质上还是会改动了我们的代码。那么我们还有没有更好的方式呢?其实我们可以基于服务器的改造
解决方法3:配置服务器的
ngix的配置
server {
listen 80; #监听80端口
server_name demo.com; #本地域名
location / {
proxy_pass http://XXXX.com; #把所有请求都转发到此需要提供服务的端口下
add_header Access-Control-Allow-Headers $http_access_control_request_headers';
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;
#判断如果进入的是与预检查
if ($request_method = OPTIONS){
return 200;
}
}
}
.apache配置
//修改vhost文件
<virtualhost *:80="">
DocumentRoot "C:/htdocs/demo" #目录路径
ServerName demo.com #域名
##ErrorLog "logs/dummy-host.localhost-error.log"
##CustomLog "logs/dummy-host.localhost-access.log" common
#设置转发(需要开启 proxy_module,proxy_http)
ProxyPass/ http://XXXX.com
#把请求头的Access-Controller-Request-Headerss值返回到Access-Control-Allow-Headers
Header always set Access-Control-Allow-Headers "expr=%{req:Access-Controller-Request-Headers}"
#把请求头的orgin值返回到Access-Control-Allow-Orgin
Header always set Access-Control-Allow-Orgin "expr=%{req:orgin}"
Header always set Access-Control-Allow-Methods "*"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Max-Age "3600"
#处理预检命令OPTIONS,直接返回204(开启 headers_module,rewrite_module)
RewriteEngine On
RewriteCond%{REQUEST_METHOD}OPTIONS
RewriteRule^(.*)$"/"[R=204,L]
</virtualhost>
以上的服务器配置就是用于跨域请求的被调用方的配置
#我们刚刚讨论完了被调用方的设置。那么我们再来说一下调用方的设置。因为在我们实际的开发中,有时候被调用方有可能是不配合我们进行跨域访问的修改的,那么我们只能自己解决跨域问题了。
在一般开发中我们解决的思路就是使用反向代理。而配置反向代理只能通过我们的服务器去访问对方的服务器,从而绕过浏览器的这一个槛。
nginx:
server {
listen 80; #监听80端口
server_name demo.com; #本地域名
#后期所有的调用接口都需要使用该地址
#例如:我们访问http://aa.com/index/login
#改为:/ajaxserver/index/login
location/ajaxserver {
proxy_pass http://XXXX.com; #需要跨域访问接口的的地址
}
}
<virtualhost *:80="">
DocumentRoot "C:/htdocs/demo" #目录路径
ServerName demo.com #域名
##ErrorLog "logs/dummy-host.localhost-error.log"
##CustomLog "logs/dummy-host.localhost-access.log" common
#后期所有的调用接口都需要使用该地址
#例如:我们访问http://aa.com/index/login
#反向代理设置
ProxyPass /ajaxserver http://XXXX.com
</virtualhost>
以上就是我们在跨域工作中遇上的常见情况以及解决思路和事例代码。
接下来我将给各位同学划分一张学习计划表!
学习计划
那么问题又来了,作为萌新小白,我应该先学什么,再学什么?
既然你都问的这么直白了,我就告诉你,零基础应该从什么开始学起:
阶段一:初级网络安全工程师
接下来我将给大家安排一个为期1个月的网络安全初级计划,当你学完后,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web渗透、安全服务、安全分析等岗位;其中,如果你等保模块学的好,还可以从事等保工程师。
综合薪资区间6k~15k
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)
2、渗透测试基础(1周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等
3、操作系统基础(1周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)
4、计算机网络基础(1周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现
5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固
6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)
那么,到此为止,已经耗时1个月左右。你已经成功成为了一名“脚本小子”。那么你还想接着往下探索吗?
阶段二:中级or高级网络安全工程师(看自己能力)
综合薪资区间15k~30k
7、脚本编程学习(4周)
在网络安全领域。是否具备编程能力是“脚本小子”和真正网络安全工程师的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力。
零基础入门的同学,我建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习
搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP,IDE强烈推荐Sublime;
Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,没必要看完
用Python编写漏洞的exp,然后写一个简单的网络爬虫
PHP基本语法学习并书写一个简单的博客系统
熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选)
了解Bootstrap的布局或者CSS。
阶段三:顶级网络安全工程师
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
学习资料分享
当然,只给予计划不给予学习资料的行为无异于耍流氓,这里给大家整理了一份【282G】的网络安全工程师从入门到精通的学习资料包,可点击下方二维码链接领取哦。