# 使用Session和Cookie实现用户登录功能
在Web开发中,用户登录功能是最基础也是最重要的功能之一。本文将详细介绍如何使用Session和Cookie这两种技术来实现安全的用户登录系统。
## 一、Session与Cookie的基本概念
### Cookie
Cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
特性:
- 存储在客户端浏览器中
- 有大小限制(通常4KB左右)
- 可以设置过期时间
- 每次请求都会自动发送给服务器
### Session
Session是服务器端存储用户数据的一种机制,每个用户都有一个唯一的Session ID。
特性:
- 存储在服务器内存或数据库中
- 理论上没有大小限制
- 默认在用户关闭浏览器后失效
- 更安全,因为敏感数据存储在服务器端
## 二、登录流程的实现
### 1. 基本登录流程
```php
<?php
session_start();
// 用户提交登录表单
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// 验证用户名和密码(此处应为数据库验证)
if ($username === 'admin' && $password === '123456') {
// 登录成功,设置Session
$_SESSION['user'] = [
'username' => $username,
'login_time' => time()
];
// 设置记住我功能的Cookie
if (isset($_POST['remember'])) {
$token = bin2hex(random_bytes(32)); // 生成随机令牌
setcookie('remember_token', $token, time()+86400*30, '/');
// 应该将token存入数据库与用户关联
}
header('Location: dashboard.php');
exit;
} else {
$error = "用户名或密码错误";
}
}
?>
```
### 2. 验证登录状态
```php
<?php
session_start();
// 检查用户是否登录
function isLoggedIn() {
// 1. 检查Session
if (isset($_SESSION['user'])) {
return true;
}
// 2. 检查记住我功能的Cookie
if (isset($_COOKIE['remember_token'])) {
$token = $_COOKIE['remember_token'];
// 应该验证token是否有效(查询数据库)
// 如果有效,重建Session
$_SESSION['user'] = [
'username' => '从数据库获取的用户名',
'login_time' => time()
];
return true;
}
return false;
}
// 使用示例
if (!isLoggedIn()) {
header('Location: login.php');
exit;
}
?>
```
## 三、安全注意事项
1. **密码存储**:永远不要明文存储密码,应使用哈希算法如bcrypt
```php
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
```
2. **Session固定攻击防护**:登录成功后应重新生成Session ID
```php
session_regenerate_id(true);
```
3. **CSRF防护**:重要操作应使用CSRF令牌
```php
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
```
4. **Cookie安全设置**:
```php
setcookie(
'remember_token',
$token,
time()+86400*30,
'/',
'yourdomain.com',
true, // 仅HTTPS
true // 仅HTTP访问,禁止JavaScript
);
```
5. **Session过期时间**:
```php
// 设置Session过期时间为30分钟
ini_set('session.gc_maxlifetime', 1800);
session_set_cookie_params(1800);
```
## 四、实际应用示例
### 完整的登录系统实现
```php
<?php
// database.php - 数据库连接
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
// auth.php - 认证功能
class Auth {
private $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
session_start();
}
public function login($username, $password, $remember = false) {
// 查询用户
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
// 登录成功
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['login_time'] = time();
if ($remember) {
$token = bin2hex(random_bytes(32));
$expire = time() + 86400 * 30;
setcookie(
'remember_token',
$token,
$expire,
'/',
'',
true,
true
);
// 存储token到数据库
$stmt = $this->pdo->prepare(
"INSERT INTO user_tokens (user_id, token, expires_at)
VALUES (?, ?, ?)"
);
$stmt->execute([$user['id'], $token, date('Y-m-d H:i:s', $expire)]);
}
return true;
}
return false;
}
public function isLoggedIn() {
// 检查Session
if (isset($_SESSION['user_id'])) {
return true;
}
// 检查记住我Cookie
if (isset($_COOKIE['remember_token'])) {
$token = $_COOKIE['remember_token'];
$stmt = $this->pdo->prepare(
"SELECT u.* FROM users u
JOIN user_tokens ut ON u.id = ut.user_id
WHERE ut.token = ? AND ut.expires_at > NOW()"
);
$stmt->execute([$token]);
$user = $stmt->fetch();
if ($user) {
// 重建Session
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['login_time'] = time();
return true;
}
}
return false;
}
public function logout() {
// 删除Session
$_SESSION = [];
session_destroy();
// 删除记住我Cookie
if (isset($_COOKIE['remember_token'])) {
$token = $_COOKIE['remember_token'];
// 从数据库删除token
$stmt = $this->pdo->prepare(
"DELETE FROM user_tokens WHERE token = ?"
);
$stmt->execute([$token]);
setcookie('remember_token', '', time() - 3600, '/');
}
}
}
// 使用示例
$auth = new Auth($pdo);
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['login'])) {
$username = $_POST['username'];
$password = $_POST['password'];
$remember = isset($_POST['remember']);
if ($auth->login($username, $password, $remember)) {
header('Location: dashboard.php');
exit;
} else {
$error = "登录失败";
}
}
?>
```
## 五、总结
通过Session和Cookie实现的用户登录系统能够满足大多数Web应用的需求。Session提供了服务器端的安全存储,而Cookie则实现了跨请求的状态维持。"记住我"功能通过长期有效的Cookie实现,但要注意其安全性。
在实际开发中,还应考虑:
- 密码重置功能
- 账户锁定机制(防止暴力破解)
- 登录日志记录
- 多设备登录管理
希望本文能帮助你理解并实现一个安全的用户登录系统。如果有任何问题,欢迎在评论区留言讨论。