最近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']})↲

これでいけたみたい。