ThinkPHP6利用前端跨域请求限制实现域名授权
晓杰最近在开发一个活码引流系统,功能基本已经开发完成,正在研究授权方面的问题,下面是晓杰研究出来的结果,分享给大家,不喜勿喷!
由于前后端分离架构,前端使用了Vue2.6 后端使用了ThinkPHP6 ,刚开始开发的时候就遇到了跨域请求失败的问题。
后续将后台增加了 $header[‘Access-Control-Allow-Origin’] = * 才解决了跨域问题,到了授权问题晓杰就想着是否可以利用该机制进行授权认证,目前晓杰暂时使用该授权方案。
public static function add($param){
try {
$validate = new AppConfigValidate();
if (!$validate->scene('beforAdd')->check($param)) {
return Res::error($validate->getError());
}
$param['status']=1;
if(!$validate->scene('add')->check($param)){
return Res::error($validate->getError());
}
AppConfigModel::add($param);
LogService::write('添加','添加');
return Res::ok();
}catch (\PDOException $e){
return Res::error($e->getMessage());
}
}
正常的新增,在支付授权订单后进行回调
//利用订单回调字符串 修改站点授权状态
$param = [
'id' => $order['order_str'],
'status' =>2
];
if (!AppConfigModel::edit($param)) {
return 'fail';
}
//修改成功后 查询授权站点域名
$appInfo = AppConfigModel::findById($order['order_str']);
$redis = new Redis();
//加入Redis 后面会讲到这个作用
$redisKey = "newSoft:whiteHost:".$appInfo['app_domain'];
$redis ->set($redisKey,1);
晓杰刚开始直接用查询数据库方式进行授权检测,但是考虑因为这个授权检测每次请求都会进行查询数据库,并发多了对服务器压力会变成负担,所以就想了个方案,Redis,刚开始还用array存储白名单 然后再进行in_array 判断,晓杰觉得还是繁琐,一不做二不休 直接利用RedisKey是否存在进行判断。下面是实现代码,如有不足之处希望大家指出。
<?php
namespace app\common\middleware;
use app\common\utils\Massage;
use app\common\utils\Res;
use app\group\appConfig\model\AppConfigModel;
use Closure;
use think\cache\driver\Redis;
use think\Config;
class AllowCrossDomain
{
protected $cookieDomain;
protected $header = [
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => 1800,
'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With,token',
];
public function __construct(Config $config)
{
$this->cookieDomain = $config->get('cookie.domain', '');
}
//校验白名单
private static function checkWhiteHost($host){
$redis = new Redis();
$redisKey = "newSoft:whiteHost:localhost";
//先判断localhost是否存在 不存在说明没有进行初始化
if (empty($redis ->get($redisKey))){
$map[] = ['status', '=', 2];
$whiteHostList = AppConfigModel::list($map);
$redis = new Redis();
foreach ($whiteHostList as $key => $value){
$redisKey = "newSoft:whiteHost:".$value['app_domain'];
$redis ->set($redisKey,1);
}
$redisKey = "newSoft:whiteHost:localhost";
$redis ->set($redisKey,1);
$redisKey = "newSoft:whiteHost:127.0.0.1";
$redis ->set($redisKey,1);
}
//组装RedisKey
$redisKey = "newSoft:whiteHost:".$host;
if (empty($redis ->get($redisKey))){
//不存在返回false
return false;
}
return true;
}
public function handle($request, Closure $next, ?array $header = [])
{
$header = !empty($header) ? array_merge($this->header, $header) : $this->header;
if (!isset($header['Access-Control-Allow-Origin'])) {
$origin = $request->header('origin');
//获取请求host
$host = parse_url($origin)['host'];
//校验白名单
if (!self::checkWhiteHost($host)){
//失败返回站点未授权
return Res::error(Massage::WEBSITE_ERROR);
die();
}
$header['Access-Control-Allow-Origin'] = $origin;
}
return $next($request)->header($header);
}
}
#效果
刚测试没增加127.0.0.1这个域名白名单
增加进白名单后请求成功
Soujer
声明:本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。联系邮箱:400#tom.com