API 平台授权与身份验证

Posted

技术标签:

【中文标题】API 平台授权与身份验证【英文标题】:API Platform authorization vs authentication 【发布时间】:2019-12-23 06:53:18 【问题描述】:

我正在使用 API Platform 开发一个 API,我正在努力解决如何保护 API。

我的前端应用程序(博客网站)包含不需要用户登录即可查看的内容(公共内容)。要从 API 中获取此内容,我不需要对用户进行身份验证,但我仍然需要授权应用程序以防止每个人都能够调用 API。一些示例路线是:

GET /api/blogs
GET /api/blogs/id

用户仍然可以登录以访问网站的其他部分(受保护的内容)。对于那些 API 调用,我需要对用户进行身份验证以检查他们的角色(管理员或其他人)。一些示例路线是:

POST /api/users
POST /api/blogs

official documentation 建议使用 JWT 进行身份验证,但这意味着用户必须登录才能查看公共内容。在security.yaml 我试过这个:

access_control:
  -  path: ^/api/blogs, roles: IS_AUTHENTICATED_ANONYMOUSLY 
  -  path: ^/api/users, roles: ROLE_ADMIN 

但是/api/blogs 被列入白名单,每个人或任何应用程序都可以从 API 调用它。

这是我security.yaml的全部内容:

security:
  encoders:
    App\Entity\User:
      id: App\Security\PasswordEncoder

  providers:
    app_user_provider:
      entity:
        class: App\Entity\User
        property: email
  firewalls:
    dev:
      pattern: ^/(_(profiler|wdt)|css|images|js)/
      security: false

    main:
      pattern: ^/api/
      stateless: true
      anonymous: true
      provider: app_user_provider
      json_login:
        check_path: api_authenticate
        username_path: email
        password_path: password
        success_handler: lexik_jwt_authentication.handler.authentication_success
        failure_handler: lexik_jwt_authentication.handler.authentication_failure
      guard:
        authenticators:
          - lexik_jwt_authentication.jwt_token_authenticator

  access_control:
    -  path: ^/api/blogs, roles: IS_AUTHENTICATED_ANONYMOUSLY 
    -  path: ^/api/users, roles: ROLE_ADMIN 

我的问题是,在我的情况下处理授权和身份验证的正确方法是什么? JWT 是否足以兼顾两者?我需要在数据库中创建一个特殊的 API 用户吗?

【问题讨论】:

@yivi 感谢您的回复。等我到电脑前去看看 【参考方案1】:

“JSON Web 令牌”(JWT) 只不过是客户端(浏览器)告诉应用程序“声明”的一种方式(例如 “我是 John Appleseed,用户编号 123”) 应用程序可以验证。

它可以这样做是因为声明是由应用程序首先生成并加密签名的:任何篡改此声明并且应用程序都会知道它是无效声明。

因此,JWT 仅对身份验证有用:验证系统中的用户身份。例如:你是谁?

授权在成功验证后发生。应用程序是否根据您的身份确定您有权或无权访问哪些资源或操作。例如:你可以这样做吗?

通常,在 Symfony 中有两种处理授权的方式。您可以在security.yaml 上配置access_control 键,或者如果您的要求更复杂,您可以在控制器中处理它。

在您的情况下,使用 JWT 令牌并配置 access_control 应该绰绰有余。您的 API 中有 public 部分,任何用户都可以查询 (IS_AUTHENTICATED_ANONYMOUSLY),以及只有经过身份验证的用户才能访问 ROLE_ADMINprivate 部分。

进一步阅读:

Authentication and Authorization Symfony Denying Access

【讨论】:

感谢您的回答。但是,如果我将公共部分设置为IS_AUTHENTICATED_ANONYMOUSLY,这是否意味着任何知道 API 端点的人都可以直接调用 API?如果我仍然想保护 API 以便只有授权的应用程序可以调用 API,该怎么办? 我不明白你在说什么。您要么希望 API 的一部分公开,要么不希望它公开。阅读您的问题,您似乎希望 /api/blogs/ 是公开的(因此,无需登录即可访问),而 /api/users/ 是私有的(只有经过身份验证和授权的用户才能访问)。如果不是这样,您可能需要进一步解释您想要完成的任务。 我想我要把 API 设为私有 API,只有内部应用程序才能调用它。然后我只需要担心使用 JWT 授权用户并保护特定端点。感谢您的帮助。【参考方案2】:

通过适当的 CORS(允许来源)设置阻止其他网站(应用)访问您的 API。如果您在 nginx / php-fpm 组合中使用 Nginx 作为反向代理,这可以在 PHP (Symfony) 级别或 Nginx 级别上完成。

如果您的 API 仅用于服务器到服务器的通信,您还可以在标头或请求中添加一些特定的“站点密钥哈希”。与您请求 Google API 时类似。但这是前端到后端通信的重点,因为密钥在前端是可见且不安全的。

【讨论】:

以上是关于API 平台授权与身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Azure API 管理 - 与底层服务进行身份验证和授权同步

OAuth 2 将服务器-服务器 API 调用的身份验证与授权分开

身份验证和精细授权

工具系列 | HTTP API 身份验证和授权

SOA:Rails 多个客户端的用户身份验证和 api 授权

如何使用 FusionAuth API 密钥对 HotChocolate Graph API 进行身份验证/授权