PHP 怎么服务身份

wen PHP项目 2

本文目录导读:

PHP 怎么服务身份

  1. API 服务身份认证(最常用)
  2. 服务间身份认证(微服务架构)
  3. 会话身份管理
  4. 客户端证书认证(mTLS)
  5. 最佳实践建议
  6. 安全最佳实践

在 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');
    }
}

安全最佳实践

  1. 使用 HTTPS:所有认证信息必须通过 HTTPS 传输
  2. Token 过期:设置合理的过期时间
  3. 速率限制:防止暴力破解
  4. 输入验证:严格验证所有输入
  5. 安全存储:密码使用 bcrypt 或 argon2 加密
  6. 日志记录:记录所有认证尝试
  7. 最小权限:授予最小必要的权限
  8. 定期轮换:定期更换密钥和证书

选择哪种方案取决于你的具体需求:

  • 单体应用:使用 Session 认证
  • API 服务:使用 JWT 或 OAuth
  • 微服务架构:使用服务间身份认证(mTLS 或 HMAC)
  • 第三方接入:使用 OAuth 2.0

抱歉,评论功能暂时关闭!