关于 php:session_set_save_handler 导致登录循环 | 珊瑚贝

session_set_save_handler causing login loop


我正在尝试使用 session_set_save_handler() 将会话写入数据库。我遇到了一个无限循环,我的系统想要让我登录,但找不到会话,所以它让我退出……但会话显然存在 – 只是不在表中。

无论如何,这是我的会话函数代码 – 我不认为这里有什么问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

// session.functions.php

$db = new mysqli(“127.0.0.1”,“user”,“pass”,“db”);
// define ‘openSession()’ function
function openSession($sessionPath, $sessionName) {
    return true;
}

// define ‘closeSession()’ function
function closeSession() {
    return true;
}

// define ‘readSession()’ method
function readSession($sessionId) {
    global $db;
    // escape session ID
        $sessionId = $db->real_escape_string($sessionId);
    $result = $db->query(“SELECT sessiondata FROM sessions WHERE
sessionid=’$sessionId‘ AND expiry > NOW()”
);
    if ($result->num_rows > 0) {
        $row = $result->fetchRow();
        return $row[‘sessiondata’];
    }
    // return empty string
    return“”;
}

// define ‘writeSession()’ function
function writeSession($sessionId, $sessionData) {
    global $db;
    $expiry = time() + get_cfg_var(‘session.gc_maxlifetime’) 1;
    // escape session ID & session data
        $sessionId = $db->real_escape_string($sessionId);
        $sessionData = $db->real_escape_string($sessionData);
    $result = $db->query(“SELECT sessionid FROM sessions WHERE
sessionid=’$sessionId‘”
);
    // check if a new session must be stored or an existing one must be updated
    ($result->num_rows > 0) ? $db->query(“UPDATE sessions SET     sessionid=’$sessionId‘,expiry=’$expiry‘,sessiondata=
$sessionData‘ WHERE sessionid=’$sessionId‘”
) or die(mysqli_error($db)) : $db->query(“INSERT INTO sessions (sessionid,expiry,sessiondata) VALUES (‘$sessionId‘,’$expiry‘,’$sessionData‘)”) or die(mysqli_error($db));
    return true;
}

// define ‘destroySession()’ function
function destroySession($sessionId) {
    global $db;
    // escape session ID
        $sessionId = $db->real_escape_string($sessionId);
    $db->query(“DELETE FROM sessions WHERE sessionid=’$sessionId‘”);
    return true;
}

// define ‘gcSession()’ function
function gcSession($maxlifetime) {
    global $db;
    $db->query(“DELETE FROM sessions WHERE expiry < NOW()”);
    return true;
}

?>

这是登录的会话设置:

1
$this->set_session(array_merge($rs->fetch_assoc(), array(‘expires’ => time() + (15 * 60))));

按功能设置:

1
2
3
4
5
private function set_session($a=false) {
    if (!empty($a)) {
        $_SESSION[‘exp_user’] = $a;
    }
}

我的登录系统如何检查我是否已经登录?

1
2
3
4
5
6
7
public function check_status() {
    if (empty($_SESSION[‘exp_user’]) || @$_SESSION[‘exp_user’][‘expires’] < time()) {
        return false;
    } else {
        return true;
    }
}

原来,$_SESSION的值,根据var_dump是array(0) { }

以及检查 Web 应用程序本身:

1
2
3
4
5
6
7
8
// This is in authorisation.php

if(empty($_SESSION[‘exp_user’]) || @$_SESSION[‘exp_user’][‘expires’] < time()) {
        header(“location:/login.php”);  //@ redirect
} else {
    $_SESSION[‘exp_user’][‘expires’] = time()+(15*60);  //@ renew 15 minutes
        //echo $SID = session_id();
}

现在,这就是我在顶部的 index.php 文件中的内容:

1
2
3
4
require(‘includes/session.functions.php’);
session_set_save_handler(‘openSession’, ‘closeSession’, ‘readSession’, ‘writeSession’, ‘destroySession’, ‘gcSession’);
session_start();
include(‘includes/authorisation.php’);

这是数据库:

SQL

如果我注释掉 session_set_save_handler(),我们不会得到循环,但是,如果我保持它在那里运行,我会得到索引和登录系统之间的循环(已经登录 -> 索引 ::check登录循环。)

1
2
3
print_r(session_set_save_handler(‘openSession’, ‘closeSession’, ‘readSession’, ‘writeSession’, ‘destroySession’, ‘gcSession’)); == 1

var_dump(session_set_save_handler(‘openSession’, ‘closeSession’, ‘readSession’, ‘writeSession’, ‘destroySession’, ‘gcSession’)); == bool(true)

知道我做错了什么吗?

  • 您的数据库架构丢失。加上一个教程:在数据库中存储会话
  • get_magic_quotes_gpc() 和数据库转义是两个不同的主题。不要混合它们。
  • 添加了数据库模式并从代码中删除了 get_magic_quotes_gpc()。
  • 检查session_set_save_handler的返回值,失败返回FALSE,成功返回TRUE。
  • bool(true) 或 1。显然,它可以使用 print_r 和 var_dump 检查
  • 好的。下一个:当您将其写入数据库时??,您需要转义 id 旁边的 $sessionData 。
  • 只是在脚本中更改了它:)
  • 因此,为了更好地调试,请删除重定向标头。只需打印一个链接而不是一条消息。然后 exit; 在该点停止执行(也可以使用标题)。然后是 var_dump if 之前的 $_SESSION。这将为您提供更多信息,并且您不会自动循环。
  • ok,$_SESSION的值,根据var_dump是array(0) { }
  • 如果会话正确存储在数据库中(检查会话数据是否实际包含某些内容),则读取失败。如果会话数据库中的数据为空,则写入失败。
  • 在我看来,就像写作失败了:调用非成员函数来转义 $sessionID。
  • 调用该函数时,看起来全局数据库对象已经被销毁。我想知道为什么,也许您在某处未设置 $db 变量?这是手册中的其他一些重要说明: 注意:直到输出流关闭后才会执行”写入”处理程序。因此,”write”处理程序中调试语句的输出将永远不会在浏览器中看到。如果需要调试输出,建议将调试输出写入文件。
  • Nopem $db 永远不会取消设置,我什至在 session.functions.php 中重新定义了它
  • 这是我发现的: 注意:未定义的变量:第 35 行 /home/erp/public_html/includes/session.functions.php 中的 sessionId。它完美地写入数据库 – (通过使用函数输入任意数据进行检查)。
  • 检查第 35 行,这里的代码没有行号。
  • 第 35 行是 $sessionId = $db->real_escape_string($sessionId);
  • 这边比较晚,祝你进一步调试好运。
  • 谢谢hakre,现在是12:26:/
  • 外部参考:stackoverflow.com/questions/6418856/…


您似乎混淆了两种不同的时间格式。在 mysql 中,NOW() 以以下格式为您提供时间:

Returns the current date and time as a value in ‘YYYY-MM-DD HH:MM:SS’ or YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is used in a string or numeric context.

在 php 中,time() 给你:

Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).

在您的 sql 语句中,您正在比较两者,您可以吗?因为它们是完全不同的格式。

  • 在服务器上的脚本中修复。没有骰子。



原来有一个额外的 session_start(),它会重置会话。


来源:https://www.codenong.com/6418222/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_8922.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?