2015-10-25 42 views
6

說明:自定義用戶身份驗證基礎

我一直在使用Laravel了一堆項目的現在。 在Laravel中實現用戶身份驗證很簡單。現在,我正在處理的結構有點不同 - 我本地沒有databaseusers表。我必須進行API調用以查詢我需要的內容。


我已經試過

public function postSignIn(){ 

    $username  = strtolower(Input::get('username')); 
    $password_api = VSE::user('password',$username); // abc <----- 
    $password  = Input::get('password'); // abc <----- 


    if ($password == $password_api) { 
     //Log user in 
     $auth = Auth::attempt(); // Stuck here <---- 
    } 

    if ($auth) { 
     return Redirect::to('/dashboard')->with('success', 'Hi '. $username .' ! You have been successfully logged in.'); 
    } 
    else { 
     return Redirect::to('/')->with('error', 'Username/Password Wrong')->withInput(Request::except('password'))->with('username', $username); 
    } 
    } 

更新

我在VSE類使用一個簡單的命令shell_exec連接到API

public static function user($attr, $username) { 

     $data = shell_exec('curl '.env('API_HOST').'vse/accounts'); 
     $raw = json_decode($data,true); 
     $array = $raw['data']; 
     return $array[$attr]; 
    } 

我希望我可以在這裏向你展示,但它在我的本地機器上的虛擬機上,所以請留在我身邊。基本上,它

執行

curl http://172.16.67.137:1234/vse/accounts < ---更新

響應

Object 
data:Array[2] 

0:Object 
DBA:"" 
account_id:111 
account_type:"admin" 
address1:"111 Park Ave" 
address2:"Floor 4" 
address3:"Suite 4011" 
city:"New York" 
customer_type:2 
display_name:"BobJ" 
email_address:"[email protected]" 
first_name:"Bob" 
last_name:"Jones" 
last_updated_utc_in_secs:200200300 
middle_names:"X." 
name_prefix:"Mr" 
name_suffix:"Jr." 
nation_code:"USA" 
non_person_name:false 
password:"abc" 
phone1:"212-555-1212" 
phone2:"" 
phone3:"" 
postal_code:"10022" 
state:"NY" 
time_zone_offset_from_utc:-5 

1:Object 
DBA:"" 
account_id:112 
account_type:"mbn" 
address1:"112 Park Ave" 
address2:"Floor 3" 
address3:"Suite 3011" 
city:"New York" 
customer_type:2 
display_name:"TomS" 
email_address:"[email protected]" 
first_name:"Tom" 
last_name:"Smith" 
last_updated_utc_in_secs:200200300 
middle_names:"Z." 
name_prefix:"Mr" 
name_suffix:"Sr." 
nation_code:"USA" 
non_person_name:false 
password:"abd" 
phone1:"212-555-2323" 
phone2:"" 
phone3:"" 
postal_code:"10022" 
state:"NY" 
time_zone_offset_from_utc:-5 
message:"Success" 
status:200 

正如你可以看到鮑勃密碼abc和湯姆是abd

+0

通過創建自己的用戶提供程序來處理登錄驗證和用戶詳細信息,您可以[擴展Laravel身份驗證系統](http://laravel.com/docs/5.1/authentication#adding-custom-authentication-drivers)並將其設置爲auth驅動程序。 – Bogdan

+0

如果您發現文檔不夠詳細,那麼您可以查看['Illuminate \ Auth \ DatabaseUserProvider'](https://github.com/laravel/framework/blob/5.1/src/Illuminate/ Auth/DatabaseUserProvider.php)源代碼來查看它如何處理數據庫存儲的用戶並將邏輯應用於遠程API。 – Bogdan

+0

如果你想提供一些代碼來展示你如何連接到API,以及你正在做什麼請求來驗證和獲取用戶信息,那麼我可能會提供一個關於如何將API調用集成到Laravel Auth驅動程序。 – Bogdan

回答

8

按照以下的步驟,你可以設置一個處理使用API​​調用讀取和驗證用戶憑據自己的認證驅動程序:

創建app/Auth/ApiUserProvider.php具有以下內容自定義的用戶提供:

namespace App\Auth; 

use Illuminate\Contracts\Auth\UserProvider; 
use Illuminate\Contracts\Auth\Authenticatable as UserContract; 

class ApiUserProvider implements UserProvider 
{ 
    /** 
    * Retrieve a user by the given credentials. 
    * 
    * @param array $credentials 
    * @return \Illuminate\Contracts\Auth\Authenticatable|null 
    */ 
    public function retrieveByCredentials(array $credentials) 
    { 
     $user = $this->getUserByUsername($credentials['username']); 

     return $this->getApiUser($user); 
    } 

    /** 
    * Retrieve a user by their unique identifier. 
    * 
    * @param mixed $identifier 
    * @return \Illuminate\Contracts\Auth\Authenticatable|null 
    */ 
    public function retrieveById($identifier) 
    { 
     $user = $this->getUserById($identifier); 

     return $this->getApiUser($user); 
    } 

    /** 
    * Validate a user against the given credentials. 
    * 
    * @param \Illuminate\Contracts\Auth\Authenticatable $user 
    * @param array $credentials 
    * @return bool 
    */ 
    public function validateCredentials(UserContract $user, array $credentials) 
    { 
     return $user->getAuthPassword() == $credentials['password']; 
    } 

    /** 
    * Get the api user. 
    * 
    * @param mixed $user 
    * @return \App\Auth\ApiUser|null 
    */ 
    protected function getApiUser($user) 
    { 
     if ($user !== null) { 
      return new ApiUser($user); 
     } 
    } 

    /** 
    * Get the use details from your API. 
    * 
    * @param string $username 
    * @return array|null 
    */ 
    protected function getUsers() 
    { 
     $ch = curl_init(); 

     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
     curl_setopt($ch, CURLOPT_URL, env('API_HOST') . 'vse/accounts'); 

     $response = curl_exec($ch); 
     $response = json_decode($response, true); 

     curl_close($ch); 

     return $response['data']; 
    } 

    protected function getUserById($id) 
    { 
     $user = []; 

     foreach ($this->getUsers() as $item) { 
      if ($item['account_id'] == $id) { 
       $user = $item; 

       break; 
      } 
     } 

     return $user ?: null; 
    } 

    protected function getUserByUsername($username) 
    { 
     $user = []; 

     foreach ($this->getUsers() as $item) { 
      if ($item['email_address'] == $username) { 
       $user = $item; 

       break; 
      } 
     } 

     return $user ?: null; 
    } 

    // The methods below need to be defined because of the Authenticatable contract 
    // but need no implementation for 'Auth::attempt' to work and can be implemented 
    // if you need their functionality 
    public function retrieveByToken($identifier, $token) { } 
    public function updateRememberToken(UserContract $user, $token) { } 
} 

2.還可以創建擴展了認證系統在app/Auth/ApiUser.php與以下提供的默認GenericUser用戶類內容:

namespace App\Auth; 

use Illuminate\Auth\GenericUser; 
use Illuminate\Contracts\Auth\Authenticatable as UserContract; 

class ApiUser extends GenericUser implements UserContract 
{ 
    public function getAuthIdentifier() 
    { 
     return $this->attributes['account_id']; 
    } 
} 

在你app/Providers/AuthServiceProvider.php文件的引導方法,註冊新的驅動程序用戶提供:

public function boot(GateContract $gate) 
{ 
    $this->registerPolicies($gate); 

    // The code below sets up the 'api' driver 
    $this->app['auth']->extend('api', function() { 
     return new \App\Auth\ApiUserProvider(); 
    }); 
} 

4。最後在config/auth.php文件中的驅動程序設置爲自定義一個:

'driver' => 'api', 

現在,您可以在您的控制器動作如下:

public function postSignIn() 
{ 
    $username = strtolower(Input::get('username')); 
    $password = Input::get('password'); 

    if (Auth::attempt(['username' => $username, 'password' => $password])) { 
     return Redirect::to('/dashboard')->with('success', 'Hi '. $username .'! You have been successfully logged in.'); 
    } else { 
     return Redirect::to('/')->with('error', 'Username/Password Wrong')->withInput(Request::except('password'))->with('username', $username); 
    } 
} 

調用Auth::user()後獲得用戶的詳細信息成功登錄後,將返回一個包含從遠程API獲取的屬性的ApiUser實例,並且看起來像這樣:

ApiUser {#143 ▼ 
    #attributes: array:10 [▼ 
    "DBA" => "" 
    "account_id" => 111 
    "account_type" => "admin" 
    "display_name" => "BobJ" 
    "email_address" => "[email protected]" 
    "first_name" => "Bob" 
    "last_name" => "Jones" 
    "password" => "abc" 
    "message" => "Success" 
    "status" => 200 
    ] 
} 

由於您尚未發佈在用戶電子郵件的API中沒有匹配項時獲得的響應示例,因此我在getUserDetails方法中設置條件以確定不存在匹配並返回null if該響應不包含data屬性或者data屬性爲空。您可以根據自己的需要更改該條件。


上面的代碼是用嘲笑的響應返回你在你的問題發佈的數據結構和它的作品非常行之有效的。

最後一點:你應該認真考慮修改API來處理用戶認證宜早不宜遲(也許使用的Oauth實現),因爲有密碼發送過來(甚至更令人擔憂的是純文本)不是你想推遲做的事情。

+0

我只是意識到我連接到了錯誤的URL。我想提出一個要求:'/ vse/accounts'。我希望你不介意在第1步中調整你的答案。我很抱歉。我只是自己調整它,但它破裂了。這是我第一次和司機打交道。 – ihue

+0

所以它應該是'/ vse/accounts/user /'。 $ username'? – Bogdan

+0

'$ username'不再是規則的一部分。只需'/ vse/accounts'就是這樣。 – ihue