Bí quyết là phải có hai mục tách ra trong tường lửa của bạn, một cho biểu mẫu đăng nhập và một cho đăng nhập facebook. Nhưng trong trường hợp của tôi, tôi có một url đăng nhập duy nhất nơi người dùng có thể đăng nhập bằng thông tin đăng nhập của mình hoặc nhấp vào một kết nối Facebook để xác thực qua API OAuth2 của Facebook bằng cách sử dụng FOSFacebookBundle
. Dưới đây là một mẫu của tập tin security.yml
cấu hình của tôi để làm cho công việc này:
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]
Và đây là một mẫu của tập tin routing.yml
tôi được sử dụng để xác định các tuyến đường an ninh cần thiết để thực hiện công việc này:
# 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 }
Sử dụng security.yml
trước đây, cơ chế bảo mật sẽ kiểm tra người dùng đã đăng nhập bằng biểu mẫu trước khi người dùng đăng nhập bằng facebook. Điều này là do thứ tự các nhà cung cấp được xác định trong số chain_provider
. Trên mỗi yêu cầu, kiểm tra FOSFacebookBundle
nếu có cookie facebook oauth2, nếu có, nó sẽ cố gắng tải người dùng của bạn. Nếu nó không tìm thấy cookie, quá trình xác thực sẽ thử một nhà cung cấp khác, nếu nó được xác định sau nhà cung cấp facebook.
Trong trường hợp của bạn, khi người dùng cố gắng truy cập url được bảo vệ (trong access_control), trang đăng nhập facebook được hiển thị và xác thực, sau đó được chuyển hướng đến trang web của bạn, cookie được tìm thấy và người dùng được xác thực thành công bởi FOSFacebookBundle
. Để kích hoạt quá trình xác thực theo cách thủ công, hãy đặt nút kết nối facebook trên trang web của bạn, sau đó, trong javascript, chuyển hướng người dùng đến một trang khác trên trang web của bạn. Bằng cách này, cookie sẽ được đặt bằng nút kết nối và FOSFacebookBundle
sẽ xác thực anh ấy theo yêu cầu tiếp theo. Những gì tôi làm, là chuyển hướng người dùng đến đường dẫn login_check cho facebook trong javascript khi nút kết nối facebook đã thành công. Bằng cách này, cơ chế bảo mật sẽ chuyển hướng anh ta đến nơi nó được ghi trong cấu hình bảo mật.
Tôi hy vọng điều này sẽ giúp bạn đạt được những gì bạn muốn. Đừng ngần ngại đặt câu hỏi thêm nếu có điều gì đó không rõ ràng.
@ Follow-up # 1
Thật vậy, bạn không thể đặt fos_userbundle
dưới nút public
trong cấu hình tường lửa vì nó không phải là một lựa chọn hợp lệ.Chuỗi fos_userbundle
được sử dụng để tham chiếu FOSUserBundle
lớp UserProvider. Tôi chưa bao giờ sử dụng gói này nhưng đọc tài liệu, bạn nên sử dụng form_login
. Bạn có thể xem tài liệu của FOSUserBundle
trong Step #5 trở xuống. Lỗi bạn đề cập là lẻ vì nó cho bạn biết rằng login_path
không được tường lửa xử lý nhưng đó là trường hợp do tường lửa khớp với bất kỳ thứ gì bắt đầu bằng một số /
(^/
). Bạn không chắc chắn những gì đang xảy ra nhưng bạn đang đi đúng hướng. Sử dụng form_login
và cố gắng kiểm tra lý do tại sao nó không hoạt động từ đó.
Kính trọng,
Matt
Tôi đã thêm một theo dõi câu trả lời của tôi. – Matt