首页 > 编程问答 >基于子域和会话验证的 OAuth 登录

基于子域和会话验证的 OAuth 登录

时间:2024-06-04 15:49:11浏览次数:17  
标签:php session oauth-2.0 subdomain

我有一个使用 OAuth 登录系统(Google、FB 等)的网站 www.example.com 当用户点击链接时,OAuth 系统会重定向到 login.example.com 并进行验证,然后重定向回 www.example.com

我正在使用基于 state 键中传递的值的请求验证。因此,当用户访问 OAuth 时,我会将 state 设置为某个随机值,当 OAuth 重定向返回我的网站时,我会检查 state 变量是否为有效请求。 不过,为了验证请求,我想使用 SESSION 存储来保存我这边的 state 。问题是,当我这样做时,子域上的 SESSION 变量是空的。

我的 SESSION 设置如下:

session_name('ID');
ini_set('session.use_cookies', 1);
ini_set('session.cookie_domain', ".example.com");
ini_set('session.cookie_samesite','Lax');

我曾尝试设置 None 代替 Lax ,但结果仍然是空的(另外,我不喜欢使用 None 进行设置)。如何解决这个问题?

除了 SESSION,还有其他验证方法吗?我不想使用任何外部库(Redis、memcache 等)。如果使用 DB,我就必须识别用户,而 IP 是不够的。


遇到的问题是跨子域共享 PHP session 的常见问题。虽然已正确设置 session.cookie_domain 来包含根域 .example.com ,但浏览器在重定向过程中可能不会发送 cookie,因为 session.cookie_samesite 设置为 Lax

以下是解决此问题并改进身份验证方法的一些建议:

1. 使用更安全的 SameSite 设置:

  • session.cookie_samesite 设置为 None 这是最可靠的跨域 cookie 共享方法,但正如所提到的,它会带来安全风险。如果必须使用 None ,请确保的网站和 OAuth 提供商都使用 HTTPS。

  • 使用更细粒度的 SameSite 控制: 可以根据请求来源动态设置 session.cookie_samesite 。例如,当重定向到 OAuth 提供商时,将其设置为 None ,并在其他情况下将其设置为 Lax

2. 使用替代的存储机制:

  • 数据库: 可以使用数据库表来存储 state 值及其关联的用户标识符。这提供了比 session 更持久和安全的存储机制。

  • 临时文件: 可以将 state 值存储在服务器上的临时文件中,并使用唯一标识符将其与用户关联。但是,这种方法不如数据库安全和可扩展。

3. 改进身份验证流程:

  • 使用 PKCE(Proof Key for Code Exchange): PKCE 是 OAuth 2.0 的扩展,可以防止授权代码拦截攻击。它通过在授权请求中包含一个代码验证器来实现这一点,该验证器用于在令牌请求期间验证客户端身份。

  • 使用 JWT(JSON Web Token): 可以使用 JWT 来存储 state 值和其他相关信息。JWT 可以由的服务器签名,以防止篡改。

以下是一些代码示例,说明如何使用数据库来存储 state 值:

1. 生成并存储 state 值:

// 生成随机的 state 值
$state = bin2hex(random_bytes(32));

// 将 state 值存储到数据库
// ... 使用选择的数据库库执行插入操作 ...
$userId = getCurrentUserId(); // 获取当前用户的 ID
insertIntoDatabase('state_table', ['state' => $state, 'user_id' => $userId]);

// 将 state 值传递给 OAuth 提供商
$oauthUrl = 'https://oauth.provider.com/authorize?state=' . $state;
header('Location: ' . $oauthUrl);

2. 验证 state 值并检索用户信息:

// 从 OAuth 提供商获取 state 值
$state = $_GET['state'];

// 从数据库中检索 state 值
// ... 使用选择的数据库库执行查询操作 ...
$result = selectFromDatabase('state_table', ['state' => $state]);

if ($result) {
  // 验证成功
  $userId = $result['user_id'];

  // ... 使用用户 ID 登录用户 ...

  // 从数据库中删除 state 值
  // ... 使用选择的数据库库执行删除操作 ...
  deleteFromDatabase('state_table', ['state' => $state]);
} else {
  // 无效的 state 值
  // ... 处理错误 ...
}

请记住,安全性是一个持续的过程。请务必及时了解最新的安全最佳实践,并定期审查和更新的身份验证机制。

标签:php,session,oauth-2.0,subdomain
From: 78573980

相关文章

  • php 图片上传
    /***文件上传**@ApiMethod(POST)*@paramstring$image上传的文件(单文件/多文件)*@paramstring$upload_dir文件夹名称(默认名:image)*/functionFilesAll($image,$upload_dir='image'){if(is_null($image)||......
  • Linux使用sz/rz命令在服务器上传下载文件 及 GIF89a图片欺骗攻击导致tmp目录很多php开
    一、Linux下使用sz/rz命令从服务器下载文件或上传文件至服务器    使用secureFX可以直接和LINUX进行文件互传,但有些服务器会要求通过中间服务器连接,无法难过SecureFX直接操作文件了,不过Linux有两个很好用的命令:sz和rzSZ:sz命令就是将服务器上的文件下载到本地电脑。s......
  • PHP对接微信公众号 进行登录操作
    1.准备好公众号的appid和appsecret,以及IP白名单2.php代码写入publicfunctionlogin_wx(){$data=Db::name('config')->where('config_key','WECHAT_CONFIG')->find();$value=json_decode($data['value......
  • CTFHUB-信息泄露-目录遍历和PHPINFO
    目录目录遍历PHPINFO目录遍历很简单,挨着把每个目录都点开看一下发现2目录下有个flag.txt文件,点开发现了本关的flagPHPINFO这关也很简单,进来之后是一个phpinfo页面,按CTRL+F键打开查询,输入flag,查找到了本关的flag ......
  • php接入eGhl支付
     参数1#订单信息2$order=$order->toArray();3$products="商品信息";4$PaymentID=substr(md5(time()),0,19);5$PageTimeout=780;6$url=env('APP_URL','');7#支付成功链接post8$MerchantApprovalU......
  • 解决php因为输出内容太短无法流式(Stream)输出问题
    实测得知,如果用PHP做流式输出每次echo的内容太短的话,就没有流式的效果了,而是会等输出的长度达到一定时前端才能拿到结果,如下:  这是我这边的测试结果,可见,这里仅接收到了两次流式输出,但是我在PHP里是输出了10次,从而证明了每次流式的内容达到一定长度时才能有流式得到效果,这个......
  • PHP利用前端跨域请求限制实现域名授权
    前言晓杰最近在开发一个活码引流系统,功能基本已经开发完成,正在研究授权方面的问题,下面是晓杰研究出来的结果,分享给大家,不喜勿喷!研究过程由于前后端分离架构,前端使用了Vue2.6后端使用了ThinkPHP6,刚开始开发的时候就遇到了跨域请求失败的问题。后续将后台增加了$hea......
  • PHP历理 做一个计算24点的功能重构版
    注意:同样存在少数计算不出24的现象,不过已经接近完善了<?phpset_time_limit(0);$values=array(2,4,10,10);$result=24;$list=array();echo"<pre>";@makeValue($values);print_r($list);functionmakeValue($values,$set=array()){$words=array(&......
  • PHP历理 做一个计算24点的功能完善版
    <?php/*demo*/$tf=newTwentyFourCal();$tf->calculate(array(5,5,5,5));$tf->calculate(array(2,4,10,10));$tf->calculate(array(4,4,10,10));$tf->calculate(array(1,2,7,7));$tf->calculate(array(4,4,4,4));$tf->calculate(......
  • PHP历理 做一个计算24点的功能
    注意:有些计算24点的数字无法计算出来。不建议使用。<?phpfunctioncalculate24($nums){$operators=['+','-','*','/'];$combinations=[];foreach($numsas$num1){foreach($numsas$num2){if($n......