最近Titanium Mobile使ってスマホアプリを作ろうかなと思って色々試してるんだけど、ログイン認証する時にはまったので、メモ
参考In Appcelerator Titanium, how can I get Django's CSRF token?(Stack Overflow)
Titanium MobileでのPOST
HTTPClientを使って、例えば次のように書く。UIの設計部分とかそんなのは省略。
var client = Ti.Network.createHTTPClient({
onerror: function(e){
Ti.API.debug(e.error);
alert('error');
},
onload: function(e){
var item = JSON.parse(this.responseText);
if(item.status==1){//例としてstatusを返すという設定にしているのでこんな感じにしてる
alert('ログインしました');
}else{
alert('ログイン失敗しました');
}
}
});
client.open('POST','http://url/to/login');
client.send({username:'hoge',password:'fuga'});
Djangoでのユーザー認証
Djangoでユーザー認証しようとすると例えばこんな感じ(viewだけ) REST API作るために、Django REST frameworkを使ってるので、そのままコピペしても使えないけど、@部分を消して、Responseとなっている箇所を自力でJSON出力すれば良いと思う。Django REST frameworkについてはどっかで書く。
# views.py
from rest_framework import viewsets↲
from rest_framework.response import Response↲
from rest_framework.decorators import api_view
from django.contrib.auth import login,authenticate
@api_view(['GET','POST'])
def do_login(request):↲
status = 0↲
if request.user.is_authenticated():↲
status = 1↲
else:↲
if request.method == 'POST':↲
username = request.POST['username']↲
password = request.POST['password']↲
user = authenticate(username=username,password=password)↲
if user is not None:↲
status = 1↲
login(request,user)↲
else:↲
return Response({"status":status})↲
return Response({"status":status})↲
↲
で、実際やってみるとレスポンスはこんな感じになる
```js
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
そういえばDjangoでCSRF対策してるんだった。
# settings.py
MIDDLEWARE_CLASSES = ( .... 'django.middleware.csrf.CsrfViewMiddleware', .... )
ajaxでやり取りする部分だけ、MIDDLEWARE_CLASSESから削除するって手もあるけど、[Django APIリファレンス](http://docs.djangoproject.jp/en/latest/ref/contrib/csrf.html)に書いてあるようにX-CSRFToken という独自ヘッダーに CSRF トークンの 値を設定するという対処をやってみた。
```js
function getCRSF(){
var xhr = Ti.Network.createHTTPClient({
onload: function(e){
var item = JSON.parse(this.responseText);
Ti.App.Properties.setString("csrf", item.csrf);
}
});
xhr.open('GET','http://url/to/login');
xhr.send();
}
これを書いて、getCRSFを先にどこかで実行しておいて 実際のリクエストはさっきのコードをこんな感じで修正する
client.open('POST','http://url/to/login');
client.setRequestHeader('X-CSRFToken', Ti.App.Properties.getString("csrf"));//これを追加
client.send({username:'hoge',password:'fuga'});
Django側のコードはGETの時にcsrfのトークンを戻すように書き換える
```py
views.py
from django.core.context_processors import csrf #を追加
上のviews.pyの14行目をこんな感じで修正
return Response({"status":status,"csrf":csrf(request)['csrf_token']})↲
これでいけたみたい。