我一直在努力设置FOSUserBundle/RestBundle/OAuthServerBundle三重奏,以创建一个无头后端,然后我可以在上面放置一个单独的前端,并最终扩展到移动设备,以及可能的第三方API访问。我根据可用的各种资源和说明进行了常规配置,并且可以使用客户端凭据生成访问令牌。
正在添加到的应用程序是一个现有的应用程序,它使用标准的Symfony/Twig进行前端/后端交互,并使用FOSUserBundle进行身份验证。
我有两个与身份验证流程相关的问题。
- 我希望用户能够访问 API 的某些部分,而无需通过客户端级别进行身份验证,并且某些部分需要用户级身份验证来验证他们是否拥有请求的资源。我没有找到做到这一点的方法。我发现一些帖子在谈论这种可能性,但没有给出如何实现它的任何方向。我相信我需要在控制器级别检查适当的访问权限,也许使用自定义投票者,因为检查"IS_AUTHENTICATED_FULLY"在向客户端进行身份验证后恢复为真。我希望能够以编程方式对用户进行身份验证,绕过 UI 登录表单 - 这可能只是覆盖 FOSUserBundle 登录控制器,但我不确定。 我要么需要
- 创建一个没有访问令牌过期的客户端,要么需要找到实现刷新令牌的方法。我真的不明白为什么我自己的应用程序需要刷新令牌,但如果这是标准方法,我可以遵循规范。
下面是一些相关的代码,尽管总的来说,这些代码是从FOSOAuthServer设置指南中复制过来的非常标准的。
安全.yml
security:
encoders:
FOSUserBundleModelUserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
oauth_token:
pattern: ^/oauth/v2/token
security: false
rest:
pattern: ^/rest(?!/doc)
fos_oauth: true
stateless: true
anonymous: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
success_handler: security.authentication.success_handler
use_referer: true
logout: true
anonymous: true
access_control:
- { path: ^/rest, roles: [ IS_AUTHENTICATED_FULLY ] }
config.yml 代码段
fos_user:
db_driver: orm
firewall_name: main
user_class: AppBundleEntityUser
registration:
form:
type: AppBundleFormTypeRegistrationFormType
profile:
form:
type: user_profile
fos_oauth_server:
db_driver: orm
client_class: AppBundleEntityClient
access_token_class: AppBundleEntityAccessToken
refresh_token_class: AppBundleEntityRefreshToken
auth_code_class: AppBundleEntityAuthCode
service:
user_provider: fos_user.user_provider.username_email
options:
supported_scopes: user
fos_rest:
view:
view_response_listener: force
formats:
json: true
templating_formats:
html: true
mime_types:
json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
jpg: ['image/jpeg']
png: ['image/png']
body_listener: true
param_fetcher_listener: true
allowed_methods_listener: true
format_listener:
rules:
- { path: ^/, priorities: [html, json], fallback_format: json, prefer_extension: false }
AD 1)我在security.yml
用两个防火墙解决了你的问题。 由于Symfony正在寻找security.yml
的第一个匹配项,因此我设置了第一个防火墙以允许匿名用户进入:
api_anonym_area:
pattern: (^/api/forgotten-password/.*)
stateless: true
fos_oauth: true
anonymous: true
我用正则表达式捕获 URL 并给出anonymous: true
作为第二个防火墙,我有捕获所有内容的正则表达式
api_auth_area:
pattern: ^/
fos_oauth: true
stateless: true
anonymous: false
所以在你的例子中,如果你想让匿名用户访问/rest/doc,在你的firewall:rest
前面放这样的东西:
rest_doc:
pattern: ^/rest/doc
fos_oauth: true
stateless: true
anonymous: true
公元2)拥有无限的访问令牌生存期不是很好的做法,但您可以通过将大整数设置为access_token_lifetime
来config.yml
执行此操作:
fos_oauth_server:
service:
options:
access_token_lifetime: #number in seconds#
仅使用刷新令牌登录
/oauth/v2/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
它在FOSOAuthServerBundle中开箱即用