9

Wydaje się, że bardzo niewiele jest aktualnych zasobów dotyczących integracji logowania na Facebooku z komponentem uwierzytelniania online cakephp. Znalazłem następujące zasoby:Jak mogę zintegrować logowanie do Facebook SDK z cakephp 2.x?

  1. Stary Bakery Article przy użyciu cakephp 1.3? i starsza wersja Facebooku SDK
  2. Cakephp Plugin by webtechnick, który wydaje się być w rozwoju

Poza tym znalazłem żadnych ostatecznych środków. Chciałem, aby integracja była tak elastyczna (bez użycia magicznej wtyczki), jak to tylko możliwe. Po wielu badaniach w końcu wypaliłem przyzwoite rozwiązanie, które dziś tu podzielam. Proszę przyczynić się, ponieważ jestem raczej nowy do ciasta.

Odpowiedz

29

Integracja CakePHP 2.x Auth z Facebooka Auth do uwierzytelnienia użytkownika szwu

Na początek należy zapoznać się na fantastycznej CakePHP Auth Component i postępuj Simple Authentication and Authorization Application tutorial z 2.x książki CakePHP (zakładając, że również po dwa pierwsze tutoriale z serii. Po zakończeniu, należy udało się zbudować prostą aplikację CakePHP z uwierzytelniania i autoryzacji użytkowników.

następnie należy pobrać facebook SDK i uzyskać App ID z facebook.


Najpierw skopiujmy plik Facebook do aplikacji/sprzedawców. Następnie zaimportujemy i zainicjujemy go w metodzie AppController beforeFilter.

//app/Controller/AppController.php 

public function beforeFilter() { 
    App::import('Vendor', 'facebook-php-sdk-master/src/facebook'); 
    $this->Facebook = new Facebook(array(
     'appId'  => 'App_ID_of_facebook', 
     'secret' => 'App_Secret' 

    )); 

    $this->Auth->allow('index', 'view'); 
} 

Inicjujemy pakiet SDK Facebooka w AppController, dzięki czemu będziemy mieć do niego dostęp za pośrednictwem aplikacji. Następnie wygenerujemy adres URL logowania na Facebooku przy użyciu zestawu SDK i przekażemy go do widoku. Zwykle robię to w metodzie beforeRender.

Uwaga: Powyższe dane konfiguracyjne (appId & secret) najlepiej zapisywać w App/Config/facebook.php. Powinieneś wtedy użyć cake Configure.

//app/Controller/AppController.php 

public function beforeRender() { 
    $this->set('fb_login_url', $this->Facebook->getLoginUrl(array('redirect_uri' => Router::url(array('controller' => 'users', 'action' => 'login'), true)))); 
    $this->set('user', $this->Auth->user()); 
} 

Będziemy aktualizować nasz układ tak, że możemy wyświetlić ten link do facebook logowania dla wszystkich użytkowników, którzy nie zalogowany. Zauważ, jak ustaliliśmy redirect_uri naszego działania aplikacji użytkownika/login. Jest tak, że gdy facebook uwierzytelnił użytkownika, możemy zalogować go również za pomocą Cake :: Auth. Istnieją różne korzyści z tego, including the solution for this question.

<!-- App/Views/Layouts/default.ctp just after <div id="content"> --> 
<?php 
    if($user) echo 'Welcome ' . $user['username']; 
    else { 
     echo $this->Html->link('Facebook Login', $fb_login_url) . ' | '; 
     echo $this->Html->link('Logout', array('controller' => 'user', 'action' => 'logout')); 
?> 

Gdy użytkownik kliknie link logowania, facebook SDK będzie zalogować użytkownika i przekierować je do naszej aplikacji Users/login. Zaktualizujemy tę akcję, aby obsłużyć to:

// App/Controller/UsersController.php 
// Handles login attempts from both facebook SDK and local 
public function login() 
{ 
    // If it is a post request we can assume this is a local login request 
    if ($this->request->isPost()){ 
     if ($this->Auth->login()){ 
      $this->redirect($this->Auth->redirectUrl()); 
     } else { 
      $this->Session->setFlash(__('Invalid Username or password. Try again.')); 
     } 
    } 

    // When facebook login is used, facebook always returns $_GET['code']. 
    elseif($this->request->query('code')){ 

     // User login successful 
     $fb_user = $this->Facebook->getUser();   # Returns facebook user_id 
     if ($fb_user){ 
      $fb_user = $this->Facebook->api('/me');  # Returns user information 

      // We will varify if a local user exists first 
      $local_user = $this->User->find('first', array(
       'conditions' => array('username' => $fb_user['email']) 
      )); 

      // If exists, we will log them in 
      if ($local_user){ 
       $this->Auth->login($local_user['User']);   # Manual Login 
       $this->redirect($this->Auth->redirectUrl()); 
      } 

      // Otherwise we ll add a new user (Registration) 
      else { 
       $data['User'] = array(
        'username'  => $fb_user['email'],        # Normally Unique 
        'password'  => AuthComponent::password(uniqid(md5(mt_rand()))), # Set random password 
        'role'   => 'author' 
       ); 

       // You should change this part to include data validation 
       $this->User->save($data, array('validate' => false)); 

       // After registration we will redirect them back here so they will be logged in 
       $this->redirect(Router::url('/users/login?code=true', true)); 
      } 
     } 

     else{ 
      // User login failed.. 
     } 
    } 
} 

I skończymy! Większość ciężkiego podnoszenia odbywa się za pomocą tej akcji, jak widać. Najlepiej przenieść część powyższego kodu do UserModel. Oto podsumowanie tego, co się dzieje.

Najpierw sprawdzamy, czy żądanie logowania jest wysyłane z formularza logowania naszej aplikacji @ Użytkownicy/login. Jeśli tak, to po prostu logujemy użytkownika.W przeciwnym razie sprawdzamy, czy użytkownik istnieje w naszej bazie danych i czy loguje się do niego lub tworzy nowego użytkownika, a następnie loguje go.

Należy zweryfikować użytkownika tutaj, wysyłając więcej niż e-mail, np. Jego facebook_id . W przeciwnym razie istnieje ryzyko, że użytkownik może zmienić e-mail na Facebooku i przejąć innego użytkownika aplikacji.

Happy Coding!

+0

Witam Shafee, podążyłem za wami przykładem, jednak z jakiegoś powodu otrzymuję tę wiadomość 1 na 10 razy. "OAuthException: aktywny token dostępu musi być użyty do zapytania informacji o bieżącym użytkowniku" Czy masz jakieś rozwiązania? – Chris

+0

Wydaje się być prawidłowym podejściem (jeszcze nie testowane). Czy mógłbyś oznaczyć to jako akceptowaną odpowiedź, ponieważ tego właśnie używasz? – Nunser

+0

Dziękuję człowieku, bardzo mi to pomogło, jedyne, co chciałbym osiągnąć to mieć wyskakujące okna logowania, zamiast przekierowania do nowego adresu URL: dodanie '" display "=>" popup ",' do getLoginUrl nie działa. Dzięki – dav