跨域是Web开发中常见的问题,解决跨域的方法也有很多。本文以CORS(跨域资源访问)方式和大家一起来了解一下针对PHP语言,如何设置允许多域名访问。
首先,我们还需要对一些基础知识有了解。
(1)服务器变量
针对PHP语言而言,服务器变量存储在$_SERVER数组中,在这个数组中有一个特殊的键值:HTTP_ORIGIN。这个键只在跨域的时候才会存在值,同源时为空字符串。
(2)响应头设置允许某域名访问:access-control-allow-origin
通过PHP的header函数可以设置允许某域名跨域访问,形式为header('access_control_allow_origin:*')。
OK,下面直接上代码:
$allow_origin = [ 'a.hhsy.cc', 'b.hhsy.cc', ]; $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : ''; //跨域访问的时候才会存在此字段 if (in_array($origin, $allow_origin)) { header('Access-Control-Allow-Origin:' . $origin); } else { return; }
note:
有一点要特别注意:通过接口工具请求接口时 $_SERVER['HTTP_ORIGIN'] 变量也为空字符串,如果你的服务外网可以访问,那你一定要注意了。
================20181107 更新===============
背景:
11月2号服务上线,上线之后发现邮件组里收到了一些乱七八糟的邮件而且数据库里也插入了一些乱码的数据。可以判定,后端服务被攻击了。
追查:
查看线上机器日志,发现日志中记录的来源域名均为空,之前做的策略无效。后端Web Server是Nginx,在经过外网到内网流量调度、接入层转发之后,业务中无法取到 $_SERVER['HTTP_ORIGIN'] 变量。
解决:
针对这种情况,想了以后几种解决方案:
(1)在Nginx中配置跨域
(2)做邮箱(手机号)验证码校验
(3)前端做拖图校验
第一种方案实践不可行,不知道是不是配置的问题,不起作用。
第三种方案需要使用到PHP的GD库、redis缓存以及开发量大,也弃用。
经过与PM FE UE商定,最终采用手机号进行验证码校验。
经过两天的开发、测试、上线,目前线上尚未发现之前的攻击问题。
note:后端服务接口不可能完全避免被刷,可做的就是增加黑客的攻击成本。