2009-09-09 6 views
6

私はCakePHPプロジェクトに取り組んでおり、現在、そのユーザ認証部分を構築中です。問題は私の認証情報(パスワードなど)がデータベースに保存されていないことです。認証ソースはLDAPですが、私の質問は非データベースソースにも等しく適用されます。CakePHP(LDAP)の代替認証ソース

Cakeは、ローカルデータベースに存在する場合にのみパスワードを処理するように見えます。 The Cake Cookbook suggests$this->Auth->authorize変数を使用して認可手順を提供するために別のコントローラ/モデル/オブジェクトに伝えることができますが、コードを見ると(具体的にはthe Auth::startup() function)、Cakeは常にデータベースをクエリしようとします最初に一致するユーザー名/パスワードを入力してから、Auth->authorizeで指定した代替オブジェクトを探します。つまり、authorizeを変更すると、第2レベルのフィルタが追加されるだけで、データベース参照が置き換えられることはありません。

// The process 
1. User provides details 
2. Cake checks the database 
3. If OK, then check the custom object method 
4. If OK, return true 

// What I'd like: 
1. User provides details. 
2. Check the custom object method 
3. If OK, return true 
4. Profit. 

コアファイルをハッキングしないでこれを行うにはどうすればよいですか?

+0

+1 – Stephen

答えて

8

は、このアプローチは、自動的にアカウントを作成します「ブリッジ」として動作します成功したログイン用:

// app/controllers/components/ldap_auth.php 
<?php 
App::import('Component', 'Auth'); 
class LdapAuthComponent extends AuthComponent { 
/** 
* Don't hash passwords 
*/ 
    function hashPasswords($data){ 
     return $data; 
    } 
/** 
* We will initially identify the user 
*/ 
    function identify($user=null, $conditions=null) { 
     // bind credentials against ldap 
     $ldapUser = $this->_ldapAuth($user); // do your stuff 
     if (!$ldapUser) { 
      return null; // if bind fails, then return null (as stated in api) 
     } 
     // get the cake model you would normally be authenticating against 
     $model =& $this->getModel(); // default is User 
     // check for existing User in mysql 
     $user = $model->find('first', array('conditions' => array(
      'username' => $ldapUser['cn'] 
     )); 
     // if no existing User, create a new User 
     if (!$user) { 
      $user = $model->save(array('User' => array(
       'username' => $ldapUser['cn'], 
       // .. map needed ldap fields to mysql fields .. 
      ))); 
      if (!$user) { 
       $this->cakeError('ldapCreateUser'); 
      } 
      // pass the id of the newly created User to Auth's identify 
      return parent::identify($model->id, $conditions); 
     } 
     // pass the id of the existing User to Auth's identify 
     return parent::identify($user[$this->userModel][$model->primaryKey], $conditions); 
    } 
/** 
* Lets check LDAP 
* 
* @return mixed Array of user data from ldap, or false if bind fails 
*/ 
    function _ldapAuth($user) { 
     $username = $user[$this->userModel][$this->fields['username']]; 
     $password = $user[$this->userModel][$this->fields['password']]; 
     // use the php ldap functions here 
     return $ldapUser; 
    } 
} 
?> 

は、使用アプリケーションにLdapAuthAuthへのすべての参照を交換したり、instructions hereに従ってください。保護_ldapAuth()方法LdapUserモデルに抽象化することができ、かつそのモデルLdapSourceから読み出され、LDAPサーバーの接続設定database.php設定であること、そして必要があるべきであるがこと

注意LdapAuthComponentは、設定可能なフィールドマッピングを使用するように調整する必要がありますが、これらは「ただ完了する」必要条件ではありません。 :)

1

Auth::authorizeは実際にはモデルデータの代わりではなく、単にモデルデータに追加されます。

5.2.6.10 authorize

通常、Authコンポーネントは、あなたが入力したログイン資格情報は、ユーザーモデルに格納されているものにそれらを比較することにより、正確であることを確認しようとします。ただし、適切な資格情報を判断するのに、の追加作業を行う場合があります。

LDAPの詳細をモデル内で抽象化する必要があるため、問題はありません。 Cakeはモデルのユーザ名とパスワードをチェックしますが、その回答はLDAPディレクトリから透過的に得られます。このモデルにはLDAP datasourceを実装するだけです。たぶんこれらのtwoarticlesを起動することができます。

0

私は、ケーキを比較的ドギーで受け入れられる方法でハックすることができました。

ユーザーテーブルに「パスワード」フィールドを追加し、誰でも使用できるものの、すべてのパスワードを「a」に設定しました。

は、その後、私は私のモデルにカスタムハッシュ関数を追加しました:

function hashPasswords($data) { 
    $data['User']['password'] = 'a'; 
    return $data; 
} 

そして、ハッシュにそのモデルを使用するように私のコントローラに次のように語った。

$this->Auth->authenticate = ClassRegistry::init('User'); 

これは今ではケーキの最初のステップは、常に合格することを意味(ユーザー名がテーブルに存在すると仮定します)。 authorize関数は今、そのことを行い、好きな方法を使って適切なチェックを行います。

は、基本的にこれにプロセスを変更しています:あなたは、単にLDAPに対して結合されているとMySQLからユーザデータを取得/保存されていると仮定すると、

// The process 
1. User provides details 
2. Cake checks the database **and always returns OK** 
3. If OK, then check the custom object method 
4. If OK, return true