ほんじゃらねっと

ダイエット中プログラマのブログ

djangoではてな認証APIを使う

認証APIを使ってユーザー認証を行えるようにしたい。


はてな認証API
http://auth.hatena.ne.jp/


livedoor Auth
http://auth.livedoor.com/


はてなとライブドアに認証APIがあるようで、両方同じような使い方ができるらしい。
はてなユーザーなのではてな認証を使ってみる。


あらかじめAPIキーと秘密鍵を取得しておく。
また、コールバックURLとして下記のようなURLを登録しておく。
http://hoge.sample.jp/auth/


urls.py

from django.conf.urls.defaults import *
from django.conf import settings
urlpatterns = patterns('',
(r'^$', 'sample.main.views.index'),
(r'^login_user/$', 'sample.main.account_views.login_user'),
(r'^auth/$', 'sample.main.account_views.api_auth'),
)


account_views.py

# vim:set fileencoding=utf-8:
import re
import os
import md5
import time
import urllib
import urllib2
from BeautifulSoup import BeautifulSoup
from django.contrib.auth import authenticate, login, logout
from django.db import IntegrityError
from django.http import HttpResponseRedirect, HttpResponse
from sample.main.models import *
HATENA_LOGIN_URL = "http://auth.hatena.ne.jp/auth"
HATENA_AUTH_URL = "http://auth.hatena.ne.jp/api/auth.xml"
HATENA_AUTH_API_KEY = "" # APIキー
HATENA_AUTH_SECRET_KEY = "" # 秘密鍵
DUMMY_PASSWORD = "" # django用ダミーパスワード
# はてなAPI認証を呼び出す
def login_user(request):
query = {
'api_key': HATENA_AUTH_API_KEY,
}
query["api_sig"] = _get_sig(query)
request_url = '%s?%s' % (HATENA_LOGIN_URL, urllib.urlencode(query))
return HttpResponseRedirect(request_url)
# API認証からのコールバックを受取り、ユーザ情報を取得、更新
def api_auth(request):
query = {
'api_key': HATENA_AUTH_API_KEY,
'cert': request["cert"],
}
query["api_sig"] = _get_sig(query)
# IDの取得はPOSTで行う。
res = urllib2.urlopen(HATENA_AUTH_URL, urllib.urlencode(query)).read()
bs = BeautifulSoup(res)
if bs.response.has_error.string == "false":
username = bs.response.user.find("name").string
if bs.response.user.image_url is not None:
image_url = bs.response.user.image_url.string
if bs.response.user.thumbnail_url is not None:
thumbnail_url = bs.response.user.thumbnail_url.string
user = None
try:
user = User.objects.get(username__exact=username)
except ObjectDoesNotExist:
user = User.objects.create_user(username, "", DUMMY_PASSWORD)
user.save()
user_profile = UserProfile.objects.create(user=user)
if image_url is not None:
user_profile.image_url = image_url
if thumbnail_url is not None:
user_profile.thumbnail_url = thumbnail_url
user_profile.save()
user = authenticate(username=username, password=DUMMY_PASSWORD)
if user is not None:
login(request, user)
else:
pass #TODO ログイン失敗処理
return HttpResponseRedirect('/')
def _get_sig(query):
sig = md5.new(HATENA_AUTH_SECRET_KEY)
keys = query.keys()
keys.sort()
for key in keys:
sig.update(key)
sig.update(query[key])
return sig.hexdigest()


あとはHTMLなりmxmlなりから http://hoge.sample.jp/login_user/ へのリンクを
張っておくとクリックした時にはてな認証が行われ、そのユーザーによる認証が
許可されていればhttp://hoge.sample.js/auth/ が呼び出される。


hmacライブラリでMD5を使ってみたが、なぜかうまくいかなかったのでmd5を使った。
djangoでユーザーの認証状況を把握するためにダミーパスワードでユーザーを登録、
認証するようにしたが、もう少しいい方法がありそうな気がする。