如何使用php开发单点登录?
单点登录(SSO)是一种身份验证技术,它使您在多个应用程序中只需一次登录即可访问。在这种情况下,您不必再次登录每个应用程序,因为您的凭据已在认证服务之间共享。单点登录在实施中大大简化了用户认证过程并提高了安全性。
本文将向您介绍如何使用PHP编写单点登录系统。我们将使用简单的示例来演示实现细节,并附上实现代码。
实现方案
我们将开发一个简单的单点登录系统,该系统由以下组成:
- 主登录应用程序
- 共享身份验证服务
- 一组外部应用程序(本例中为两个),通过共享身份验证服务进行身份验证。
所有应用程序都在同一服务器上运行,并且我们将使用PHP作为我们的编程语言。
实现步骤
以下是我们需要采取的步骤:
- 创建数据库表
- 用户登录主应用程序
- 将登录信息存储在共享身份验证服务中
- 获取登录状态并访问外部应用程序
- 注销处理
创建数据库表
我们需要在MySQL中创建两个表:用户表和会话表。
用户表将保存用户信息,包括用户名和哈希密码:
CREATE TABLE users (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(255) NOT NULL
);
会话表将保存会话信息:
CREATE TABLE sessions (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
session_id VARCHAR(255) NOT NULL,
user_id INT(11) NOT NULL,
expires_at DATETIME NOT NULL
);
用户登录主应用程序
主应用程序的第一步是提供登录功能。这里我们将创建一个简单的登录表单,在用户输入用户名和密码时进行验证。如果验证成功,我们将把用户的ID和会话信息存储在数据库中。
下面是我们的登录表单和PHP代码:
<form action="login.php" method="post">
<label for="username">Username:</label>
<input type="text" name="username" id="username"><br>
<label for="password">Password:</label>
<input type="password" name="password" id="password"><br>
<input type="submit" value="Login">
</form>
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// 在数据库中检查用户名和密码
$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $db->prepare("SELECT * FROM users WHERE username=:username LIMIT 1");
$stmt->execute(array(':username' => $username));
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
// 将会话信息存储到数据库中
$session_id = session_id();
$user_id = $user['id'];
$expires_at = date('Y-m-d H:i:s', strtotime('+1 day'));
$stmt = $db->prepare("INSERT INTO sessions (session_id, user_id, expires_at) VALUES (:session_id, :user_id, :expires_at)");
$stmt->execute(array(
':session_id' => $session_id,
':user_id' => $user_id,
':expires_at' => $expires_at
));
// 将会话ID存储到cookie中
setcookie('session_id', $session_id, strtotime($expires_at), '/');
// 跳转到外部应用程序
header('Location: http://localhost/external_app_1/index.php');
exit();
} else {
echo 'Invalid username or password';
}
}
?>
将登录信息存储在共享身份验证服务中
我们需要为我们的外部应用程序提供一个可以共享的服务,以便可以在主应用程序和外部应用程序之间共享会话信息。
我们用Redis作为我们的共享服务。我们将使用一个 PHP Redis 客户端,它可以与 Redis 服务器进行通信。
这个共享服务将用于存储会话数据,我们需要提供一个使用 PHP Predis 客户端连接到 Redis 并存储数据的函数:
<?php
require __DIR__ . '/vendor/autoload.php';
function setSessionData($sessionId, $userId, $expiresAt) {
$redis = new Predis\Client('tcp://127.0.0.1:6379');
$redis->set($sessionId, json_encode(compact('userId', 'expiresAt')));
$redis->expireat($sessionId, strtotime($expiresAt));
}
?>
获取登录状态并访问外部应用程序
现在,我们需要在外部应用程序中检查用户是否登录。我们将使用会话ID作为标识,这个ID已存储在共享服务中。
如果用户已登录,则我们将允许他们访问外部应用程序。否则,我们将重定向到主应用程序以进行登录。
以下是我们的代码:
<?php
session_start();
require __DIR__ . '/../vendor/autoload.php';
if (isset($_COOKIE['session_id'])) {
$redis = new Predis\Client('tcp://127.0.0.1:6379');
$sessionId = $_COOKIE['session_id'];
$sessionData = $redis->get($sessionId);
if ($sessionData) {
$sessionData = json_decode($sessionData, true);
if (strtotime($sessionData['expiresAt']) > time()) {
$_SESSION['user_id'] = $sessionData['userId'];
} else {
$redis->del($sessionId);
setcookie('session_id', '', time() - 3600, '/');
header('Location: http://localhost/main_app/login.php');
exit();
}
}
}
if (!isset($_SESSION['user_id'])) {
header('Location: http://localhost/main_app/login.php');
exit();
}
?>
注销处理
我们还需要提供注销功能,这将删除存储在数据库和共享服务中的会话信息。以下是我们的注销代码:
<?php
require __DIR__ . '/../vendor/autoload.php';
if (isset($_COOKIE['session_id'])) {
$redis = new Predis\Client('tcp://127.0.0.1:6379');
$sessionId = $_COOKIE['session_id'];
$redis->del($sessionId);
setcookie('session_id', '', time() - 3600, '/');
}
?>
结论
在本文中,我们讨论了如何使用PHP编写单点登录系统,这个系统由以下组成:
- 主登录应用程序
- 共享身份验证服务
- 一组外部应用程序,通过共享身份验证服务进行身份验证。
我们提供了一个简单的示例来演示实现细节,并附上了实现代码。
评论 (0)