WP Rails Authenticate

懲りずにRailsとWodpressの認証を結合する試みの続き。 integration apiを使って一定の成功は見たものの、実はdevelopment環境(cookieセッション)でしか動かなかった。production環境はmemcachedセッションを採用しているが、integration apiはcookieセッションとActiveRecordセッションにしか対応してない。memcachedセッションに対応させようと色々やってみたが挫折した。遺憾ながらこの手は放棄するッ! と言うわけでもう一つのプラグイン、WP Rails Authenticateを使ってみることにした。

このプラグインは、Wordpress側にだけインストールし、Railsアプリケーションのdatabase.ymlの場所を設定してやれば、そこからRailsのデータベース情報を拾って独自に認証してくれるというもの。直接SQLを叩くのでMySQLにしか対応していないが、Rails側には一切手を加えないで済む。 前提としてphpのライブラリsyckとmysqliが必要なのでpearなどでインストールしておく。(今回はportsで入れた) プラグインそのままだと色々不具合がある。SQLは決め打ちなので、Railsの認証に合わせて直接変更する必要があるし、暗号化方式もsha512で決め打ちされていた(restful_authenticationはsha1だった)。 さらにWPもRailsもUTFなのに日本語が化ける問題が発生。これを回避するためにmysqli_set_charset($db, “utf8”)を加えておく。 以上を色々いじってようやく動くようになったので、パッチを載せておく。 なお、Railsのusersテーブルはrestful_authenticationを基本に、こちらを参考にメールアドレスでログインするようにしたもので、nicknameカラムは表示のみに使用している。

--- wp-rails-authenticate.php.orig	2010-02-15 00:37:22.000000000 +0900
+++ wp-rails-authenticate.php	2010-07-20 12:49:49.000000000 +0900
@@ -45,8 +45,8 @@
      * @param stdClass the user object returned from the rails app's database
      * @return string the encrypted password
      */
-    function apply_encryption($data) {
-      return hash('sha512', "--{$data->salt}--{$password}--");
+    function apply_encryption($data, $password, $enctype) {
+      return hash($enctype, "--{$data->salt}--{$password}--");
     }
     
     /*
@@ -98,7 +98,7 @@
         // load our database credentials from the rails database.yml file
         $yaml = file_get_contents($config_file);
         $data = syck_load($yaml);
-        $credentials = $data['staging'];
+        $credentials = $data['production'];
         extract($credentials);
         $this->db = new mysqli($host, $username, $password, $database);
       }
@@ -107,16 +107,18 @@
     
     function authenticate_rails($username, $password) {
       $db = $this->oc_db();
-      $query = sprintf("SELECT `id`, `first_name`, `last_name`, `email`, `encrypted_password`, `salt` FROM `users` WHERE `email` = '%s'", 
+      $query = sprintf("SELECT `id`, `email`, `crypted_password`, `salt`, `nickname` FROM `users` WHERE `email` = '%s'", 
         mysql_real_escape_string($username));
+      mysqli_set_charset($db, "utf8");
+      $db->query($query);
       $login = $db->query($query);
       if (! $login->num_rows || $login->num_rows == 0) {
         return false;
       }
       $data = $login->fetch_object();
-      
-      $encrypted_password = $this->apply_encryption($data);
-      if ($encrypted_password == $data->encrypted_password) {
+
+      $encrypted_password = $this->apply_encryption($data, $password, 'sha1');
+      if ($encrypted_password == $data->crypted_password) {
         return $data;
       }
       return false;
@@ -195,10 +197,11 @@
       $user_data = array(
         'user_pass' => $password,
         'user_login' => $oc_user->email,
-        'first_name' => $oc_user->first_name,
-        'last_name' => $oc_user->last_name,
-        'display_name' => $oc_user->first_name . ' '. $oc_user->last_name,
-        'email' => $oc_user->email
+        'first_name' => $oc_user->nickname,
+        'last_name' => '',
+        'nickname' => $oc_user->nickname,
+        'display_name' => $oc_user->nickname,
+        'user_email' => $oc_user->email
       );
       
       require_once(WPINC . DIRECTORY_SEPARATOR . 'registration.php');