我需要有一个单独的url的纯登录形式(用户名/密码)已经存在于/login,和一些url/login-via-facebook通过FOSFacebookBundle oauth过程登录。
现在我无法理解如何通过url触发oauth-facebook过程,只有当我尝试访问在"access_control"中列出的url时才有效。
提前感谢!
@Matt,非常感谢你的解释!我试着跟随你的答案,但仍然有一个问题,我没有提到我已经使用FOSUserBundle,
my security.yml
:
providers:
chain_provider:
providers: [fos_userbundle, fos_facebook]
fos_userbundle:
id: fos_user.user_manager
fos_facebook:
id: fos_facebook.auth
firewalls:
public:
pattern: ^/
fos_facebook:
app_url: ""
server_url: ""
login_path: /login
check_path: /login_check/facebook
provider: fos_userbundle
fos_userbundle:
login_path: /login
check_path: /login_check/form
provider: fos_userbundle
anonymous: true
logout: true`
因此,此时它抛出一个异常:InvalidConfigurationException: Unrecognized options "fos_userbundle" under "security.firewalls.public"
,如果我在公共防火墙中将fos_userbundle更改为form_login(但我应该这样做吗?),它抛出一个异常You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.
您检查过安检了吗?yml:
factories:
- "%kernel.root_dir%/../vendor/bundles/FOS/FacebookBundle/Resources/config/security_factories.xml"
这很重要,因为它将对服务中缺少的选项收费。
诀窍是在防火墙中有两个分开的条目,一个用于表单登录,一个用于facebook登录。但在我的情况下,我有一个登录url,用户可以使用他的凭据登录,也可以使用FOSFacebookBundle
单击Facebook连接通过Facebook OAuth2 API进行身份验证。下面是我的security.yml
配置文件的示例,以使此工作:
security:
factories:
- "%kernel.root_dir%/../vendor/bundles/FOS/FacebookBundle/Resources/config/security_factories.xml"
providers:
chain_provider:
providers: [acme.form_provider, acme.facebook_provider]
acme.form_provider:
id: acme.user_provider.form
acme.facebook_provider:
id: acme.user_provider.facebook
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
public:
pattern: ^/
fos_facebook:
app_url: "your_app_url"
server_url: "your_server_url"
login_path: /login
check_path: /login_check/facebook
provider: acme.facebook_provider
form_login:
login_path: /login
check_path: /login_check/form
provider: acme.form_provider
anonymous: true
logout: true
role_hierarchy:
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
这里是我的routing.yml
文件的示例,用于定义使此工作所需的安全路由:
# This is defined to let the user log in. The controller for
# route display the login form and a facebook connect button
_security_login:
pattern: /login
defaults: { _controller: AcmeAcmeBundle:Main:login }
# This is defined for the form login authentication,
# no controller is associated with it
_security_check_form:
pattern: /login_check/form
# This is defined for facebook login authentication,
# a controller is associated with it but does nothing
_security_check_facebook:
pattern: /login_check/facebook
defaults: { _controller: AcmeAcmeBundle:Main:loginCheckFacebook }
_security_logout:
pattern: /logout
defaults: { _controller: AcmeAcmeBundle:Main:logout }
在使用security.yml
之前,安全机制将在用户使用facebook登录之前检查使用表单登录的用户。这是因为在chain_provider
中定义提供程序的顺序。对于每个请求,FOSFacebookBundle
检查是否存在facebook oauth2 cookie,如果存在,则尝试加载您的用户。如果无法找到cookie,则身份验证过程将尝试另一个提供商,如果它是在facebook提供商之后定义的。
在您的情况下,当用户试图去到一个受保护的url(在access_control), facebook登录页面显示,他的身份验证,然后他被重定向到您的网站,cookie被发现,用户通过FOSFacebookBundle
成功认证。要手动触发身份验证过程,请在您的站点上放置一个facebook连接按钮,然后用javascript将用户重定向到您站点的另一个页面。这样,cookie将由连接按钮设置,FOSFacebookBundle
将在下一个请求时对他进行身份验证。我所做的是,当facebook连接按钮成功时,将用户重定向到javascript中facebook的login_check路径。这样,安全机制将把他重定向到安全配置中声明的位置。
我希望这将帮助你实现你想要的。如果有不清楚的地方,可以毫不犹豫地进一步提问。
@Follow-up # 1
实际上,您不能将fos_userbundle
放在防火墙配置中的节点public
下,因为它不是一个有效的选项。字符串fos_userbundle
用于引用FOSUserBundle
UserProvider类。我从未使用过这个包,但是阅读文档,你应该使用form_login
。您可以查看步骤#5和下面的FOSUserBundle
文档。您提到的错误很奇怪,因为它告诉您login_path
不是由防火墙处理的,但由于防火墙匹配以/
(^/
)开头的任何内容,因此情况就是这样。不知道哪里出了问题,但你的方向是对的。使用form_login
并尝试检查为什么它不能从那里工作。
问候,
马特
这里有一个简单的Bundle示例,它实现了FOSUserBundle和FOSFacebookBundle,如果你想看的话https://github.com/ollietb/OhFOSFacebookUserBundle