You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP Slim框架中保障API端点安全?已遇未授权访问问题

解决Slim API未授权访问问题:仅允许认证用户访问

嘿,你的问题其实很典型——前端做了登录,但API本身没加身份校验拦截,导致任何人直接敲URL就能拉走敏感数据。下面给你几个适配Slim框架的实用方案,一步步搞定这个问题:

方案一:用JWT(JSON Web Token)做身份认证(前后端分离首选)

这是前后端分离项目最常用的方式,核心思路是:登录成功后后端给前端发一个加密令牌,前端每次请求API都带着这个令牌,后端校验令牌合法才放行。

  1. 安装JWT依赖
    先在你的Slim项目里安装Firebase的JWT库,执行命令:

    composer require firebase/php-jwt
    
  2. 后端生成JWT(登录接口改造)
    当Angular前端发起登录请求,验证用户名密码正确后,生成JWT返回给前端:

    use Firebase\JWT\JWT;
    
    $app->post('/login', function ($request, $response) {
        $data = $request->getParsedBody();
        // 这里写你的用户校验逻辑,比如查数据库验证账号密码
        $user = checkUserCredentials($data['username'], $data['password']);
        
        if ($user) {
            $secretKey = getenv('JWT_SECRET'); // 密钥存在环境变量里,别硬编码!
            $payload = [
                'iss' => 'your-api-domain', // 签发者(你的API域名)
                'aud' => 'your-angular-app', // 受众(你的前端应用标识)
                'iat' => time(), // 签发时间
                'exp' => time() + 3600, // 过期时间(1小时,可按需调整)
                'user_id' => $user['id']
            ];
            
            $token = JWT::encode($payload, $secretKey, 'HS256');
            return $response->withJson(['token' => $token]);
        } else {
            return $response->withStatus(401)->withJson(['error' => '用户名或密码错误']);
        }
    });
    
  3. 创建Slim认证中间件
    写一个中间件,用来校验每个请求的JWT是否合法:

    use Firebase\JWT\JWT;
    use Firebase\JWT\Key;
    
    class AuthMiddleware {
        public function __invoke($request, $handler) {
            // 从请求头获取Authorization字段
            $authHeader = $request->getHeaderLine('Authorization');
            
            // 没有令牌或者格式不对,直接返回401未授权
            if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) {
                return $handler->handle($request)->withStatus(401)->withJson([
                    'error' => '未授权访问,请先登录'
                ]);
            }
    
            // 提取令牌部分(去掉前面的"Bearer ")
            $token = substr($authHeader, 7);
            $secretKey = getenv('JWT_SECRET');
    
            try {
                // 解码并校验令牌
                $decoded = JWT::decode($token, new Key($secretKey, 'HS256'));
                // 把解码后的用户信息放进请求对象,后续路由可以直接调用
                $request = $request->withAttribute('user', $decoded);
            } catch (\Exception $e) {
                // 令牌无效或过期,返回错误提示
                return $handler->handle($request)->withStatus(401)->withJson([
                    'error' => '无效或过期的登录令牌'
                ]);
            }
    
            // 校验通过,继续处理请求
            return $handler->handle($request);
        }
    }
    
  4. 给需要保护的路由添加中间件
    你可以给单个路由加,也可以给整个路由组加,比如保护/slimapi/customers下的所有接口:

    // 给客户相关路由组添加认证中间件
    $app->group('/slimapi/customers', function ($group) {
        $group->get('/view', function ($request, $response) {
            // 这里可以通过$request->getAttribute('user')拿到当前登录用户信息
            $customers = // 查询客户数据的业务逻辑
            return $response->withJson($customers);
        });
        // 其他客户相关接口...
    })->add(new AuthMiddleware());
    
  5. 前端Angular配置自动带令牌
    用Angular的HttpInterceptor,让所有API请求自动在请求头带上Authorization: Bearer <token>,这样合法登录后的请求都会被API放行,而直接浏览器访问的话没有这个头,就会被拦截返回错误。

方案二:用Session+HttpOnly Cookie(同域项目适用)

如果你的Angular前端和Slim API是同域的,也可以用传统的Session认证:

  1. 登录接口启动Session

    $app->post('/login', function ($request, $response) {
        session_start();
        $data = $request->getParsedBody();
        $user = checkUserCredentials($data['username'], $data['password']);
        
        if ($user) {
            $_SESSION['user_id'] = $user['id'];
            // 设置HttpOnly Cookie,防止XSS窃取Session
            setcookie('session_id', session_id(), time() + 3600, '/', '', true, true);
            return $response->withJson(['message' => '登录成功']);
        } else {
            return $response->withStatus(401)->withJson(['error' => '登录失败']);
        }
    });
    
  2. 创建Session校验中间件

    class SessionAuthMiddleware {
        public function __invoke($request, $handler) {
            session_start();
            // 检查Session是否存在用户标识
            if (!isset($_SESSION['user_id'])) {
                return $handler->handle($request)->withStatus(401)->withJson([
                    'error' => '未授权访问,请先登录'
                ]);
            }
            return $handler->handle($request);
        }
    }
    
  3. 给路由添加中间件
    和JWT方案一样,把中间件加到需要保护的路由上即可。

额外安全提醒

  • 别依赖检查Referer头来限制访问,这个很容易被伪造,完全不安全
  • 所有API请求必须用HTTPS,防止令牌或Session被窃听
  • JWT要设置合理的过期时间,同时实现刷新令牌机制,避免用户频繁登录
  • 敏感接口除了身份认证,还要加权限校验(比如普通用户只能看自己的客户数据,管理员才能看全部)

内容的提问来源于stack exchange,提问作者shehan96

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:50:31