gpt4 book ai didi

php - getJSON 和 session_regenerate_id()

转载 作者:可可西里 更新时间:2023-11-01 12:38:39 27 4
gpt4 key购买 nike

我正在从受 session 保护的页面执行标准的 getJSON 查询:

$.getJSON('queries.php',{q: 'updateEvent', param1: p1},
function(data){
...
}
);

在我的 session 构造函数中,我设置了以下内容:

function startSession() 
{
ini_set('session.use_only_cookies', SESSION_USE_ONLY_COOKIES);

$cookieParams = session_get_cookie_params();
session_set_cookie_params(
$cookieParams["lifetime"],
$cookieParams["path"],
$cookieParams["domain"],
SESSION_SECURE,
SESSION_HTTP_ONLY
);

session_start();

if ( SESSION_REGENERATE_ID )
session_regenerate_id(SESSION_REGENERATE_ID);
}

如果我将 SESSION_REGENERATE_ID 设置为 true,那么我的 getJSON 会发送一个 token ,但会收到一个不同的 token ,从而导致请求失败。所以目前我正在处理设置为 false 的 SESSION_REGENERATE_ID

有没有办法让 getJSON 在这种情况下工作?

编辑:所有文件都在同一个域下。

我们有包含 js 的 index.php,我们有 queries.php,这是 ajax 请求调用的 php 文件,我们有 s_session.php,其中包含上面编写的构造函数。

文件 index.html 和 queries.php 在开始时都是这样保护的:

include "s_session.php"; 
if(!$login->isLoggedIn()) {
header('Content-Type: application/json');
echo json_encode(array('content' => 'Login failed'));
exit;
}

PHPSESSID 位于 set-cookie 下的 ajax 请求的 header 中。答案中返回的 PHPSESSID 与 session_regenerate_id 所预期的不同。

如果 SESSION_REGENERATE_ID 设置为 FALSE,请求将顺利通过。如果它设置为 TRUE,那么我会收到错误消息“登录失败”。

这是 isLoggedIn() :

public function isLoggedIn() {
//if $_SESSION['user_id'] is not set return false
if(ASSession::get("user_id") == null)
return false;

//if enabled, check fingerprint
if(LOGIN_FINGERPRINT == true) {
$loginString = $this->_generateLoginString();
$currentString = ASSession::get("login_fingerprint");
if($currentString != null && $currentString == $loginString)
return true;
else {
//destroy session, it is probably stolen by someone
$this->logout();
return false;
}
}

$user = new ASUser(ASSession::get("user_id"));
return $user->getInfo() !== null;
}

编辑 2:这是完整的 ASSession 代码:

class ASSession {

/**
* Start session.
*/
public static function startSession()
{
ini_set('session.use_only_cookies', SESSION_USE_ONLY_COOKIES);

session_start();
$s = $_SESSION;

$cookieParams = session_get_cookie_params();

session_set_cookie_params(
$cookieParams["lifetime"],
$cookieParams["path"],
$cookieParams["domain"],
SESSION_SECURE,
SESSION_HTTP_ONLY
);

if ( SESSION_REGENERATE_ID )
session_regenerate_id(SESSION_REGENERATE_ID);

//$_SESSION = $s;

}

/**
* Destroy session.
*/
public static function destroySession() {

$_SESSION = array();

$params = session_get_cookie_params();

setcookie( session_name(),
'',
time() - 42000,
$params["path"],
$params["domain"],
$params["secure"],
$params["httponly"]
);

session_destroy();
}

/**
* Set session data.
* @param mixed $key Key that will be used to store value.
* @param mixed $value Value that will be stored.
*/
public static function set($key, $value) {
$_SESSION[$key] = $value;
}

/**
* Unset session data with provided key.
* @param $key
*/
public static function destroy($key) {
if ( isset($_SESSION[$key]) )
unset($_SESSION[$key]);
}

/**
* Get data from $_SESSION variable.
* @param mixed $key Key used to get data from session.
* @param mixed $default This will be returned if there is no record inside
* session for given key.
* @return mixed Session value for given key.
*/
public static function get($key, $default = null) {
if(isset($_SESSION[$key]))
return $_SESSION[$key];
else
return $default;
}

}

编辑 3:这里是请求 header 和响应 cookie:

enter image description here enter image description here

我注意到在 onload 期间执行的第一个 getJSON 是成功的。在用户之后完成并由用户触发的所有其他操作均不成功

最佳答案

这主要是由竞争条件引起的,但也有可能是浏览器错误。

排除浏览器错误的情况,但提供的信息存在冲突,更具体地说是 this comment :

It is several calls, made one by one on user action, never simultaneously.

如果这些请求从未同时执行,那么这只能意味着您的浏览器无法正常运行并且会发生以下情况之一:

  • 丢弃它在响应中收到的 Set-Cookie header (如果该逻辑取决于 HttpOnly 标志,这将解释为什么网络仍然有效 :D)
  • onLoad 事件实际上在页面加载期间执行(我知道这没有意义,但如果是浏览器错误,一切皆有可能)

当然,这些不太可能发生,所以我倾向于说您实际上是在一次处理多个 AJAX 请求,在这种情况下,竞争条件是一个合理的场景:

  1. 第一个请求开始(使用您的初始 PHPSESSID)
  2. 第二个请求开始(再次使用相同的 PHPSESSID)
  3. 处理第一个请求并接收带有新 PHPSESSID 的响应
  4. 第二个请求直到现在才被阻止( session 处理程序使用锁定来防止多个进程同时修改相同的数据)并且刚刚开始使用初始 PHPSESSID,此时无效,因此会触发注销。

我会亲自查看由 onLoad 事件触发的内容 - 很容易将所有初始化逻辑放在那里而忘记这可能包括多个异步请求。


无论哪种方式,您真正的逻辑错误是这段代码:

if ( SESSION_REGENERATE_ID )
session_regenerate_id(SESSION_REGENERATE_ID);

您在两个不同的条件下使用相同的值:

  1. 确定是否完全重新生成 session ID
  2. 告诉 session_regenerate_id() 是否应该立即销毁与旧 session ID 关联的数据

立即销毁该数据的选项正是为这些异步请求的竞争条件提供解决方案,因为它们实际上是不可避免的。竞争条件在某个时候发生,无论您如何努力避免它 - 即使没有逻辑缺陷,网络延迟(例如)仍可能触发它。
保留旧 session 的数据(当然是暂时的)可以通过简单地允许“延迟”或“不同步”请求与启动时可用的任何数据一起工作来解决该问题。

session 垃圾收集器稍后会清理过期的 session 。这可能并不理想,但几乎是需要您删除数据的存储的唯一解决方案(与 Redis 等缓存存储相反,后者允许您设置 TTL 值,而不必手动删除)。

就我个人而言,我更喜欢避免在 AJAX 请求期间特别是 session ID 重新生成……如您所见,这是一堆蠕虫。 :)

关于php - getJSON 和 session_regenerate_id(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34993189/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com