我写了这段代码以安全方式启动会话
function sessionStart() {
$session_name = 'sec_session_id'; // Set a custom session name
$secure = false; // Set to true if using https.
$httponly = true; // This stops javascript being able to access the session id.
ini_set('session.use_only_cookies', 1); // Forces sessions to only use cookies.
$cookieParams = session_get_cookie_params(); // Gets current cookies params.
session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly);
session_name($session_name); // Sets the session name to the one set above.
session_start(); // Start the php session
session_regenerate_id(true); // regenerated the session, delete the old one.
}
现在我有一个问题,如果我们有这个session_regenrate_id然后我们的会话ID会在每个页面执行时改变吗?如果我为会话重新生成id我应该如何为想要登录1个月的用户使用cookie例如? 这样可以安全地将$ cookieParams [“life”]增加到1个月吗?如果没有我应该如何实现1个月?我使用ssl然后我认为我的饼干是安全的。
更新
另一种方法是将会话存储在数据库中。
<?php
/**
* PDO Session Handler
* @author Daniel15 <dan.cx>
*
* This class is actually static, but since PHP doesn't support static classes, abstract is close
* enough. You do not instantiate the class; you just call the static "init" method.
*/
abstract class PDOSession
{
private static $db;
private static $oldData;
/**
* Initialise the PDO session handler
* @param PDO PDO instance to use for database
*/
public static function init(PDO $db)
{
self::$db = $db;
// Add the session handlers
session_set_save_handler('PDOSession::open', 'PDOSession::close',
'PDOSession::read', 'PDOSession::write',
'PDOSession::destroy', 'PDOSession::garbageCollect');
session_start();
}
/**
* Session open handler
* @param string Path to save session to
* @param string Name of the session
*/
public static function open($save_path, $session_name)
{
// Nothing
return true;
}
/**
* Session close handler
*/
public static function close()
{
// Nothing
return true;
}
/**
* Session load handler. Load the session
* @param string Session ID
*/
public static function read($session_id)
{
// Load the session data from the database
$query = self::$db->prepare('
SELECT data
FROM sessions
WHERE session_id = :session_id');
$query->execute(array(':session_id' => $session_id));
return $query->fetchColumn();
}
/**
* Session save handler. Save the session
* @param string Session ID
* @param string Data to save to session
*/
public static function write($session_id, $data)
{
/* Try to update the existing session. If we can't find one, then create a new one. If you
* are using MySQL, this can be done in a single INSERT statment via INSERT ... ON
* DUPLICATE KEY UPDATE. Remove the UPDATE and edit the INSERT to do it this way.
* See http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
*
* This does two queries so you can use any DBMS.
*/
$query = self::$db->prepare('
UPDATE sessions
SET data = :data, last_activity = :last_activity
WHERE session_id = :session_id');
$query->execute(array(
':session_id' => $session_id,
':data' => $data,
'last_activity' => time()));
// No session to update? Create a new one
if ($query->rowCount() == 0)
{
self::$db
->prepare('
INSERT INTO sessions
(session_id, data, last_activity)
VALUES
(:session_id, :data, :last_activity)')
->execute(array(
':session_id' => $session_id,
':data' => $data,
'last_activity' => time())
);
}
}
/**
* Session delete handler. Delete the session from the database
* @param string Session ID
*/
public static function destroy($session_id)
{
self::$db
->prepare('
DELETE FROM sessions
WHERE session_id = :session_id')
->execute(array(':session_id' => $session_id));
}
/**
* Session garbage collector. Delete any old expired sessions
* @param int How many seconds do sessions last for?
*/
public static function garbageCollect($lifetime)
{
self::$db
->prepare('
DELETE FROM sessions
WHERE last_activity < :min_time')
->execute(array(':min_time' => time() - $lifetime));
}
}
?>
现在我应该如何在这种情况下创建cookie?
答案 0 :(得分:2)
现在我们需要让这个复选框做一些事情。也就是说,选中后,请记住用户的用户名,并将其放置在每个相应的登录页面访问的用户名字段中。为此,我决定使用cookies。我无法使用上面设置的“ID_my_site”用户名cookie,因为每次用户退出时都会被杀死。解决方案是创建一个名为“remember”的额外cookie,它也存储用户名,如下所示:
$year = time() + 31536000;
setcookie('remember_me', $_POST['username'], $year);
上面我们添加了这个额外的cookie,持续一年,这样当用户登录时会创建一个包含用户用户名的附加cookie。但是,目前尚未使用。改变:
<input type="text" name="username" maxlength="40">
为:
<input type="text" name="username" maxlength="40" value="<?php
echo $_COOKIE['remember_me']; ?>">
我们的登录表单中的现在将此用户名存储在文本字段中以供将来访问:
我们还没有完成。目前,代码正在为每个用户存储此信息。我们希望它只记住那些专门请求此功能的用户。为此,我们在创建附加cookie之前运行一个简单的检查。此检查查看是否已选中“记住我”复选框,并且仅创建我们的新cookie(如果有)。像这样:
if($_POST['remember']) {
setcookie('remember_me', $_POST['username'], $year);
}
elseif(!$_POST['remember']) {
if(isset($_COOKIE['remember_me'])) {
$past = time() - 100;
setcookie(remember_me, gone, $past);
}
}
上述代码还处理存在cookie的情况,但是用户已经确定他们不再想要记住他们,通过将任何现有的cookie设置为过去的时间,基本上将其杀死。
了解更多here ...
答案 1 :(得分:2)
详细了解其工作方式将花费更多时间来完成所有工作。但我应该能够为您提供有关其工作原理的高级摘要。
PHP会话有时间限制。一段时间后他们会被清理干净。您可以在PHP配置中延长该时间,但不能长到有效。
所以需要做的是创建另一种登录路线。这必须谨慎实施,因为不小心这样做会打开安全漏洞。
该概念可以概括为创建一个与用户关联的一次性使用唯一cookie,并可用作用户名和密码的替代。
此cookie应该是唯一的,使用随机数据生成,并与用户关联存储。它应该是有时间限制的(如果不在一两周内使用它将会过期)并在使用后重新生成。
更改用户数据(如电子邮件/密码)应该要求用户输入密码。
网站应该使用SSL来使cookie拦截变得更加困难。