WordPress と OAuth 認証を使って会員向け Web サービスを作る

WordPress で主に Twitter の OAuth を使ったり、データベースに会員情報を持っておく方法を紹介します。すべて説明していると返って分かりにくくなりますので、ポイントを押さえて説明していきますので読んでみてください。今回メインで参考にさせて頂いた記事は以下です。
PHPでTwitter APIのOAuthを使う方法まとめ – 頭ん中

WordPress のデータベースにメンバーテーブルを作成

id を WordPress 側で使い、user_id は Twitter の user_id です。user_name は Twitter での screen_name です。access_token_key と access_token_secret を保存しておけばサイト側からツイートなどを行うこともできます。

1
2
3
4
5
6
7
8
CREATE TABLE IF NOT EXISTS `wp_members` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(64) NOT NULL,
  `user_name` varchar(64) NOT NULL,
  `access_token_key` text NOT NULL,
  `access_token_secret` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;

PEAR のライブラリをすべて揃える

今回は WordPress なので無難に PEAR の OAuth のライブラリを使って認証を行います。共用サーバーなので PEAR のライブラリは WordPress のテーマファイルに includes ディレクトリを作ってそこに配置しました。配置するファイルは以下の4つです。

配置すると以下のような構成になります。

PEAR の HTTP_OAuth を改造する

HTTP_OAuth はデフォルトで Twitter の user_id と screen_name を取得することができませんが、以下のサイトを参考に HTTP_OAuth を改造することで取得できるようになります。
HTTP_OAuthでアクセストークンを取得するときにユーザIDとスクリーン名を取得できるようにするための修正 – Awesome Rapid Service

Consumer.php の HTTP_OAuth_Consumer クラスを主に変更します。

HTTP_OAuth_Consumer クラスにメンバ変数を追加。

1
2
protected $userId = null;
protected $screenName = null;

getAccessToken メソッド末尾に以下のコードを追加。

1
2
$this->setUserId($data['user_id']);
$this->setScreenName($data['screen_name']);

HTTP_OAuth_Consumer クラスにメソッドを追加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public function getUserId()
{
	return $this->userId;
}
 
public function setUserId($userId)
{
	$this->userId = $userId;
}
 
public function getScreenName()
{
	return $this->screenName;
}
 
public function setScreenName($screenName)
{
	$this->screenName = $screenName;
}

WordPress で SESSION が使えるようにする

OAuth の認証やログインの保持などには SESSION が使える必要があります。functions.php に以下のようにアクションを追加します。これで WordPress 起動時に session_start() が実行されるようになります。

1
2
3
4
function init_session_start(){
	session_start();
}
add_action('init', 'init_session_start');

WordPress で OAuth を簡単に使うライブラリ

私が自作した以下のライブラリを使えば簡単に OAuth 認証の面倒なコードの記述などをしていく必要がありません。よろしければお使いください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
class wbsOAuth
{
	const
		TWITTER_CONSUMER_KEY = '1234567890',
		TWITTER_CONSUMER_SECRET = 'qwertyuiopasdfghjklzxcvbnm',
		TWITTER_CALLBACK_URL = 'http://example.com/twitter-callback';
 
	public function __construct($service = null)
	{
		set_include_path(dirname(__FILE__) . '/includes');
		include 'HTTP/OAuth/Consumer.php';
 
		if(is_null($service)) {
			$service = $_SESSION['service'];
		} else {
			$_SESSION['service'] = $service;
		}
 
		if($service == 'twitter') {
			$this->consumer = new HTTP_OAuth_Consumer(self::TWITTER_CONSUMER_KEY, self::TWITTER_CONSUMER_SECRET);
		}
	}
 
	public function twitterLogin()
	{
		if(!$this->is_login()) {
			// Twitter へ移動する前の準備
			$this->consumer->getRequestToken('http://twitter.com/oauth/request_token', self::TWITTER_CALLBACK_URL);
			$_SESSION['request_token'] = $this->consumer->getToken();
			$_SESSION['request_token_secret'] = $this->consumer->getTokenSecret();
			$auth_url = $this->consumer->getAuthorizeUrl('http://twitter.com/oauth/authorize');
			// Twitter へ移動
			header("Location: " . $auth_url);
		} else {
			header("Location: " . '/');
		}
	}
 
	public function twitterCallback()
	{
		if(!$this->is_login()) {
			$verifier = $_GET['oauth_verifier'];
			$this->consumer->setToken($_SESSION['request_token']);
			$this->consumer->setTokenSecret($_SESSION['request_token_secret']);
			$this->consumer->getAccessToken('http://twitter.com/oauth/access_token', $verifier);
			$_SESSION['access_token'] = $this->consumer->getToken();
			$_SESSION['access_token_secret'] = $this->consumer->getTokenSecret();
			$_SESSION['user_id'] = $this->consumer->getUserId();
			$_SESSION['user_name'] = $this->consumer->getScreenName();
			$_SESSION['member_id'] = $this->memberSave(
				Array(
					'user_id' => m($_SESSION['user_id']),
					'user_name' => m($_SESSION['user_name']),
					'access_token_key' => m($_SESSION['access_token']),
					'access_token_secret' => m($_SESSION['access_token_secret'])
				)
			);
		}
		header("Location: " . '/');
	}
 
	public function logout()
	{
		if(self::is_login()) {
			$_SESSION = array();
			session_destroy();
		}
		header("Location: " . '/');
	}
 
	public function twitterPost($status)
	{
		$this->consumer->setToken($_SESSION['access_token']);
		$this->consumer->setTokenSecret($_SESSION['access_token_secret']);
		$response = $this->consumer->sendRequest("http://twitter.com/statuses/update.xml", Array('status' => $status), "POST");
	}
 
	private function memberSave($data)
	{
		if(
			isset($data['user_id']) &&
			isset($data['user_name']) &&
			isset($data['access_token_key']) &&
			isset($data['access_token_secret'])
		) {
			global $wpdb;
			$fields = array(
				'user_id' => m($data['user_id']),
				'user_name' => m($data['user_name']),
				'access_token_key' => m($data['access_token_key']),
				'access_token_secret' => ($data['access_token_secret'])
			);
			$query = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}members WHERE user_id = %s", $data['user_id']);
			$results = $wpdb->get_results($query);
			if(count($results)) {
				$where['id'] = (string) $results[0]->id;
				$insert_result = $wpdb->update($wpdb->prefix . 'members', $fields, $where);
				return $results[0]->id;
			} else {
				$insert_result = $wpdb->insert($wpdb->prefix . 'members', $fields);
				return $wpdb->insert_id;
			}
		} else {
			echo 'Member data Missing.';
		}
	}
 
	public function is_login()
	{
		if(
			isset($_SESSION['user_id']) &&
			isset($_SESSION['user_name']) &&
			isset($_SESSION['access_token']) &&
			isset($_SESSION['access_token_secret'])
		) {
			return true;
		} else {
			return false;
		}
	}
 
}
if(!function_exists('m'))
{
	function m($var)
	{
		return mysql_real_escape_string($var);
	}
}

WordPress にページを作成して各テーマファイルを設定する

ログインページを作る

WordPress でログインページというものを作ってスラッグを twitter-login にします。その後 page-twitter-login.php というテーマファイルを作って内容は以下のようにしてください。

1
2
3
<?php
$OAuth = new wbsOAuth('twitter');
$OAuth->twitterLogin();

このページにアクセスすると自動的に Twitter の認証ページにリダイレクトします。

コールバックページを作る

WordPress でコールバックページというものを作ってスラッグを twitter-callback とします。その後 page-twitter-callback.php というテーマファイルを作って内容は以下のようにします。

1
2
3
<?php
$OAuth = new wbsOAuth();
$OAuth->twitterCallback();

このページは認証後に帰ってくるページです。ここに帰ってくると自動的にデータベースに Twitter の情報をもとにメンバーデータを格納します。既にメンバーデータがデータベースにある場合は、データベースの情報が最新のものに更新されます。

ログアウトページを作る

WordPress でログアウトというものを作ってスラッグを logout とします。その後 page-logout.php というテーマファイルを作って内容は以下のようにします。

1
<?php wbsOAuth::logout(); ?>

サイドバーにログイン状況を表示

サイドバーに以下のようにしてログイン状況を表示しましょう。ログインしている場合はユーザー情報が、ログインしていない場合にはログインバナーが表示されます。リンク先も最適化していますよ。

1
2
3
4
5
6
7
8
9
10
<?php if(wbsOAuth::is_login()): ?>
	<h2><?php echo $_SESSION['user_name']; ?>さんのプロフィール</h2>
	<p class="image"><a href="http://twitter.com/<?php echo $_SESSION['user_name']; ?>"><img src="http://img.tweetimag.es/i/<?php echo $_SESSION['user_name']; ?>_b"></a></p>
	<p>ログインしている状態で夢日記を書いておけば後で自分の日記を見ることができます。</p>
	<p class="logout"><a href="/logout">ログアウト</a></p>
<?php else: ?>
	<h2>Twitter でログイン</h2>
	<p>ログインをしなくても夢日記は書けますが、ログインして夢日記を書くと、自分の夢日記をあとで読み返すことができます。</p>
	<p class="login"><a href="/twitter-login"><img src="http://si0.twimg.com/images/dev/buttons/sign-in-with-twitter-l.png"></a></p>
<?php endif; ?>

プロフィール画像を表示するのには以下のサービスが便利でした。
[twitter] TwitterAPI プロフィール写真を簡単に表示 – ウェブシステム開発【Lucen@Wiki】

ログインバナーを設置するには以下の素材が便利でした。
Overview of "Sign in with Twitter" | dev.twitter.com

あとがき

以上となります。各コードがどのように動作するのか理解した上でご利用ください。本コードの中にバグなどが御座いましたら、お手数では御座いますがコメント欄からご連絡ください。

コメント

コメントは受け付けていません。