携帯端末固有ID
DoCoMoからのアクセスの場合だけ,ログイン成功したのに次の画面に遷移するとログインが解除されてしまった!!
これは,ログイン済みの確認にUserAgentも確認しているのが原因だった…. DoCoMoの場合,携帯端末固有IDを取得しているときと,していないときでは,UserAgentが異ことが原因だった….
ということで,UserAgentの取得部分を加工することで解決しました. いや….無理矢理させた….
携帯固有IDでユーザ認証 「修正」
先日のBLOG( 携帯固有IDでユーザ認証 )にて,Djangoの認証をいじったのですが,perezvonさんのBLOGでより詳細に書かれているので記録!! とても参考になります. 「 django.contrib.authのImproperlyConfiguredCommentsAdd 」
nobu さんからも意見がありましたがーやっぱBackendは継承しないみたいですね. ということで修正.
携帯固有IDでユーザ認証
携帯端末固有IDでユーザ認証をしてみようとテストした. ちなみに,端末IDのみで認証することが危険だから実用的じゃない!!なんて話は受け流す.
端末固有IDの取得方法は,「 ウノウラボ Unoh Labs: Pythonで携帯の機種判別をする (perezvon さん)」からライブラリを利用しました.
まず,Userモデルを拡張で Profileモデルを作成.こちらにはデバイスIDを登録できる.
# project/common/models.py
class Profile(models.Model):
user = models.OneToOneField(User)
device_id = models.CharField(max_length=100, blank=True)
端末固有IDで認証するための DeviceIdBackend を作成. ModelBackendを継承して作ってみたんだが…どうなんでしょ!?
# project/common/auth/backends.py
from django.contrib.auth.backends import ModelBackend
from project.common.models import Profile
class DeviceIdBackend(ModelBackend):
def authenticate(self, device_id=None):
try:
profile = Profile.objects.get(device_id=device_id)
return profile.user
except Profile.DoesNotExist:
return None
これを settings.py に情報を追加
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'project.common.auth.backends.DeviceIdBackend',
)
とりあえず,動くかどうか views.py にログイン処理を書いてみる. forms.py を書いたりしたらスッキリに見えたりするんでしょうがーんなもん無視!
# project/app/views.py
from uamobile import detect, exceptions
from uamobile.nonmobile import NonMobileUserAgent
from django.contrib.auth import login, authenticate
from django.template import loader, RequestContext as Context
from django.http import HttpResponse, HttpResponseRedirect, Http404
def sign_in(request):
# デバイス情報の取得
try:
device = detect(request.META)
except exceptions.NoMatchingError, e:
raise Http404
# 携帯以外のアクセス処理
if isinstance(device, NonMobileUserAgent):
raise Http404
if request.method == 'POST':
# 端末固有IDからユーザ情報取得
user = authenticate(device_id = device.serialnumber)
if user is None or not user.is_active:
raise Http404
# ログイン処理(TODO:)
login(request, user)
return HttpResponseRedirect('app_template.html')
else:
# ログイン画面表示
t = loader.get_template('login_template.html')
c = Context(request, {})
return HttpResponse(t.render(c))
こんな感じでとりあえずユーザ認証はできたようだ. ちなみに,コレ携帯から試していない(笑).User Agent Switcherで偽装して成功した感じ. また,ログイン処理はSession系の処理をしないといけないはず,Cookieが使えるかとか/Getにセッションを埋め込むとか ね.面倒ね.
セッションをURLに付加
セッションIDをURLの後ろに付加させるカスタムタグを試しに作ってみた.
Cookieが無効な携帯は自動でセッションIDを付加させて欲しいなぁということでurlタグならぬーmobile_urlタグを作成. 今回は,前提として「django.core.context_processors.request」を有効へ.
# settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
)
また,MIDDLEWARE_CLASSに携帯用のUserAgentMobileMiddlewareを追記.これは 「 ウノウラボ Unoh Labs: Pythonで携帯の機種判別をする (perezvon さん)」を利用しました!! いつも参考にさせていただいてます☆ありがとうございます☆
さて,ここからmobile_urlタグの作成.内容は大したことなくおおもとのurlとURLNodeをそのまま利用しただけぇ.
# project/common/templatetags/custom_tags.py
from django.conf import settings
from django.template import Library, Node
from django.template.defaulttags import URLNode
from django.utils.encoding import iri_to_uri
from uamobile.nonmobile import NonMobileUserAgent
register = Library()
class MobileURLNode(URLNode):
def render(self, context):
url = super(MobileURLNode, self).render(context)
device = context['request'].device
# 携帯以外のアクセス処理
if isinstance(device, NonMobileUserAgent):
return url
# cookieが利用可能時処理
if device.supports_cookie():
return url
# session_idの付加
return url + iri_to_uri(
'?%s=%s' % (
settings.SESSION_COOKIE_NAME,
context['request'].session.session_key
)
)
def mobile_url(parser, token):
bits = token.contents.split(' ', 2)
if len(bits) < 2:
raise TemplateSyntaxError, "'%s' takes at least one argument (path to a view)" % bits[0]
args = []
kwargs = {}
if len(bits) > 2:
for arg in bits[2].split(','):
if '=' in arg:
k, v = arg.split('=', 1)
k = k.strip()
kwargs[k] = parser.compile_filter(v)
else:
args.append(parser.compile_filter(arg))
return MobileURLNode(bits[1], args, kwargs)
url = register.tag(mobile_url)
てな感じ,mobile_urlなんてurlをそのままコピー.ほんでもってーMobileURLNodeもURLNodeを継承してーそのまま利用. 結局,URLNodeでrender()されたURLのケツにセッションを付加させただけ. このとき,contextからデバイス情報とセッション情報を抜き取りたかったので最初に2つの作業をやったわけです.
これで,あとはテンプレートにて {% url %} を使うのと同じように {% mobile_url %} として使えば付加してくれるんじゃないかなぁ(笑)
ん~セッションIDを付加させるのを単純に ?session_key=session_value なんてしているので問題が多そう(苦笑).ここらはもう1ヒネリとか必要になりそうです. ちょいと適当なままBLOGに載せちゃった感がありますね.まぁ僕らしい僕らしい!!突っ込みがあれば是非宜しくお願いいたします!!