简单单点登录系统(SSO)的PHP实现
单点登录(Single Sign-On,SSO)是一种用户认证机制,允许用户在多个应用程序中使用同一组凭证进行登录。本文将围绕PHP语言,介绍如何开发一个简单的单点登录系统。
单点登录系统在大型企业或组织中非常有用,因为它可以简化用户登录过程,提高安全性,并减少管理成本。我们将使用PHP和MySQL来构建一个简单的SSO系统。
系统设计
我们的SSO系统将包括以下组件:
1. 认证服务器(Auth Server):负责处理用户登录请求,生成会话令牌,并存储用户会话信息。
2. 资源服务器(Resource Server):需要用户认证的服务器,通过认证服务器验证用户身份。
3. 用户数据库:存储用户信息和会话信息。
技术栈
- PHP
- MySQL
- JSON Web Tokens (JWT)
- OAuth 2.0
实现步骤
1. 创建数据库
我们需要创建一个MySQL数据库来存储用户信息和会话信息。
sql
CREATE DATABASE sso;
USE sso;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(255) NOT NULL
);
CREATE TABLE sessions (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
token VARCHAR(255) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
);
2. 用户认证服务器
认证服务器负责处理用户登录请求,验证用户凭证,并生成JWT令牌。
php
<?php
// auth_server.php
// 连接数据库
$mysqli = new mysqli("localhost", "root", "password", "sso");
// 检查连接
if ($mysqli->connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
// 检查POST请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// 验证用户凭证
$stmt = $mysqli->prepare("SELECT id, password FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->bind_result($id, $hashed_password);
$stmt->fetch();
if (password_verify($password, $hashed_password)) {
// 用户凭证验证成功,生成JWT令牌
$token = bin2hex(random_bytes(32));
$stmt = $mysqli->prepare("INSERT INTO sessions (user_id, token) VALUES (?, ?)");
$stmt->bind_param("is", $id, $token);
$stmt->execute();
// 返回JWT令牌
echo json_encode(['token' => $token]);
} else {
// 用户凭证验证失败
echo json_encode(['error' => 'Invalid credentials']);
}
$stmt->close();
$mysqli->close();
}
?>
3. 资源服务器
资源服务器需要验证JWT令牌,以确保用户有权访问受保护的资源。
php
<?php
// resource_server.php
// 连接数据库
$mysqli = new mysqli("localhost", "root", "password", "sso");
// 检查连接
if ($mysqli->connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
// 检查请求头中的Authorization字段
$auth_header = $_SERVER['Authorization'];
if (preg_match('/Bearer (.+)/', $auth_header, $matches)) {
$token = $matches[1];
// 验证JWT令牌
$stmt = $mysqli->prepare("SELECT user_id FROM sessions WHERE token = ?");
$stmt->bind_param("s", $token);
$stmt->execute();
$stmt->bind_result($user_id);
$stmt->fetch();
if ($user_id) {
// JWT令牌验证成功,用户有权访问受保护资源
echo json_encode(['message' => 'Access granted']);
} else {
// JWT令牌验证失败
echo json_encode(['error' => 'Invalid token']);
}
$stmt->close();
$mysqli->close();
} else {
// 没有提供Authorization字段
echo json_encode(['error' => 'Authorization header missing']);
}
?>
4. 测试
现在,我们可以使用Postman或其他HTTP客户端工具来测试我们的SSO系统。
1. 向认证服务器发送登录请求,获取JWT令牌。
2. 将JWT令牌添加到资源服务器的请求头中,尝试访问受保护资源。
总结
本文介绍了如何使用PHP和MySQL实现一个简单的单点登录系统。虽然这个示例非常基础,但它提供了一个SSO系统的基础框架。在实际应用中,您可能需要添加更多的安全性和功能,例如令牌刷新、会话过期和跨域资源共享(CORS)。
请注意,为了简化示例,我们省略了错误处理和安全性最佳实践。在生产环境中,您应该使用HTTPS、密码哈希、错误日志记录和适当的异常处理来确保系统的安全性。
Comments NOTHING