本文目录导读:

在 PHP 中实现“服务身份”通常涉及以下几种场景,我来分别说明:
API 服务身份认证(最常用)
JWT(JSON Web Token)认证
// 使用 firebase/php-jwt 库
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class AuthService {
private $key = 'your-secret-key';
// 生成 Token
public function generateToken($userId) {
$payload = [
'user_id' => $userId,
'iat' => time(),
'exp' => time() + (60 * 60 * 24) // 24小时过期
];
return JWT::encode($payload, $this->key, 'HS256');
}
// 验证 Token
public function verifyToken($token) {
try {
$decoded = JWT::decode($token, new Key($this->key, 'HS256'));
return $decoded;
} catch (Exception $e) {
return null;
}
}
// 中间件验证
public function authenticate($request) {
$headers = getallheaders();
if (!isset($headers['Authorization'])) {
http_response_code(401);
die('未授权');
}
$token = str_replace('Bearer ', '', $headers['Authorization']);
$user = $this->verifyToken($token);
if (!$user) {
http_response_code(401);
die('无效的Token');
}
return $user;
}
}
OAuth 2.0 认证
// 使用 league/oauth2-server 库
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Grant\PasswordGrant;
class OAuthService {
private $server;
public function __construct() {
$this->server = new AuthorizationServer(
new ClientRepository(),
new AccessTokenRepository(),
new ScopeRepository(),
__DIR__ . '/private.key',
__DIR__ . '/public.key'
);
// 添加密码授权
$passwordGrant = new PasswordGrant(
new UserRepository(),
new RefreshTokenRepository()
);
$passwordGrant->setRefreshTokenTTL(new \DateInterval('P1M'));
$this->server->enableGrantType(
$passwordGrant,
new \DateInterval('PT1H')
);
}
public function issueToken($username, $password) {
try {
$response = $this->server->respondToAccessTokenRequest(
new \GuzzleHttp\Psr7\ServerRequest(),
new \GuzzleHttp\Psr7\Response()
);
return json_decode($response->getBody(), true);
} catch (OAuthServerException $e) {
// 处理认证失败
return ['error' => $e->getMessage()];
}
}
}
服务间身份认证(微服务架构)
class ServiceIdentity {
private $serviceName;
private $privateKey;
// 服务注册时获取身份
public function registerService() {
$identity = [
'service' => $this->serviceName,
'timestamp' => time(),
'nonce' => bin2hex(random_bytes(16)),
'signature' => $this->generateSignature()
];
return $identity;
}
// 调用其他服务时携带身份
public function createAuthHeaders() {
$timestamp = time();
$nonce = bin2hex(random_bytes(16));
$message = $this->serviceName . $timestamp . $nonce;
return [
'X-Service-Name' => $this->serviceName,
'X-Timestamp' => $timestamp,
'X-Nonce' => $nonce,
'X-Signature' => $this->sign($message)
];
}
private function sign($message) {
// 使用 HMAC 或 RSA 签名
return hash_hmac('sha256', $message, $this->privateKey);
}
// 验证其他服务调用
public function validateRequest($headers) {
$service = $headers['X-Service-Name'];
$timestamp = $headers['X-Timestamp'];
$nonce = $headers['X-Nonce'];
$signature = $headers['X-Signature'];
// 检查时间戳是否过期(5分钟窗口)
if (abs(time() - $timestamp) > 300) {
return false;
}
// 验证签名
$message = $service . $timestamp . $nonce;
$expectedSignature = $this->sign($message);
return hash_equals($expectedSignature, $signature);
}
}
会话身份管理
session_start();
class SessionAuth {
// 用户登录
public function login($userId) {
session_regenerate_id(true);
$_SESSION['user_id'] = $userId;
$_SESSION['last_activity'] = time();
$_SESSION['token'] = bin2hex(random_bytes(32));
return $_SESSION['token'];
}
// 验证会话
public function validateSession() {
if (!isset($_SESSION['user_id'])) {
return false;
}
// 会话过期检查(30分钟无操作)
if (time() - $_SESSION['last_activity'] > 1800) {
$this->logout();
return false;
}
$_SESSION['last_activity'] = time();
// 防止会话固定攻击
if (!isset($_SESSION['initialized'])) {
session_regenerate_id(true);
$_SESSION['initialized'] = true;
}
return true;
}
// 注销
public function logout() {
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(
session_name(),
'',
time() - 42000,
$params["path"],
$params["domain"],
$params["secure"],
$params["httponly"]
);
}
session_destroy();
}
}
客户端证书认证(mTLS)
// Nginx 配置示例
/*
ssl_client_certificate /etc/ssl/client-ca.crt;
ssl_verify_client on;
location / {
if ($ssl_client_verify != SUCCESS) {
return 403;
}
}
*/
class CertificateAuth {
public function getClientIdentity() {
if (!isset($_SERVER['SSL_CLIENT_S_DN'])) {
return null;
}
$dn = $_SERVER['SSL_CLIENT_S_DN'];
$identity = [
'common_name' => $_SERVER['SSL_CLIENT_S_DN_CN'] ?? '',
'email' => $_SERVER['SSL_CLIENT_S_DN_emailAddress'] ?? '',
'organization' => $_SERVER['SSL_CLIENT_I_DN_O'] ?? '',
'verified' => $_SERVER['SSL_CLIENT_VERIFY'] === 'SUCCESS'
];
return $identity;
}
}
最佳实践建议
class IdentityVerifier {
// 多重验证
public function verifyIdentity($request) {
$checks = [
'token' => $this->checkToken($request),
'ip' => $this->checkIP($request),
'user_agent' => $this->checkUserAgent($request),
'rate_limit' => $this->checkRateLimit($request)
];
foreach ($checks as $check => $result) {
if (!$result['pass']) {
$this->logSecurityEvent($check, $result['reason']);
return false;
}
}
return true;
}
// 记录安全日志
private function logSecurityEvent($type, $reason) {
$log = [
'timestamp' => date('Y-m-d H:i:s'),
'type' => $type,
'reason' => $reason,
'ip' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT']
];
error_log(json_encode($log), 3, '/var/log/security.log');
}
}
安全最佳实践
- 使用 HTTPS:所有认证信息必须通过 HTTPS 传输
- Token 过期:设置合理的过期时间
- 速率限制:防止暴力破解
- 输入验证:严格验证所有输入
- 安全存储:密码使用 bcrypt 或 argon2 加密
- 日志记录:记录所有认证尝试
- 最小权限:授予最小必要的权限
- 定期轮换:定期更换密钥和证书
选择哪种方案取决于你的具体需求:
- 单体应用:使用 Session 认证
- API 服务:使用 JWT 或 OAuth
- 微服务架构:使用服务间身份认证(mTLS 或 HMAC)
- 第三方接入:使用 OAuth 2.0