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_ADMIN
的 private 部分。
进一步阅读:
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 调用的身份验证与授权分开