#使用JavaScript調用Horizon中的接口 本文主要解決了如下三個問題:git
##環境github
##horizon設置ajax
安裝django-cors-headersdjango
pip install django-cors-headers
在setting.py中配置django-cors-headers跨域
INSTALLED_APPS = [ [...] 'corsheaders', ] # CorsMiddleware 須要放在第一位 # 註釋掉CsrfViewMiddleware中間件,這樣還沒結束,由於有的view上面加了@csrf_protect裝飾器,下面的步驟要把這個裝飾給取消掉。 # 註釋掉django.contrib.sessions.middleware.SessionMiddleware,用horizon.middleware.SessionMiddleware,horizon.middleware.SessionMiddleware的代碼見下文。 MIDDLEWARE_CLASSES = ( 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', # 'django.contrib.sessions.middleware.SessionMiddleware', 'horizon.middleware.SessionMiddleware', [...] ) # CORS # https://github.com/ottoyiu/django-cors-headers CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = True # 容許js發送的request頭信息 CORS_ALLOW_HEADERS = ( 'x-requested-with', 'content-type', 'accept', 'origin', 'authorization', 'x-csrftoken', 'SESSION', ) # 容許js額外讀取的response頭信息 CORS_EXPOSE_HEADERS = ( 'SESSION', ) CORS_ALLOW_METHODS = ( 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS' ) # 將session設置長一點 SESSION_TIMEOUT = 86400
完全關閉CSRFcookie
有些view使用了@csrf_protect
,只註釋django.middleware.csrf.CsrfViewMiddleware
是沒用的,好在csrf_protect
提供了一個_dont_enforce_csrf_checks
來跳過認證,這裏寫個中間件來實現這個功能。session
(1) 在django/middleware.py
後追加以下內容:cors
class DisableCSRF(object): def process_request(self, request): setattr(request, '_dont_enforce_csrf_checks', True)
(2) 編輯settings.py
啓用該中間件dom
MIDDLEWARE_CLASSES = ( 'horizon.middleware.DisableCSRF', ... )
從header中讀取sessionurl
編輯horizon/middleware.py
,在裏面放入一個新類
SessionMiddleware
是從django.contrib.sessions.middleware.SessionMiddleware
複製過來的,並在裏面作了兩處修改,一是在process_request
中優先從request header中讀取session;二是在process_response
中將session放入response header中。
from django.utils.cache import patch_vary_headers from django.utils.http import cookie_date from django.utils.importlib import import_module class SessionMiddleware(object): def process_request(self, request): engine = import_module(settings.SESSION_ENGINE) # 優先從header獲取session if request.META.has_key("HTTP_SESSION"): session_key = request.META.get("HTTP_SESSION") else: session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None) request.session = engine.SessionStore(session_key) def process_response(self, request, response): """ If request.session was modified, or if the configuration is to save the session every time, save the changes and set a session cookie. """ try: accessed = request.session.accessed modified = request.session.modified except AttributeError: pass else: if accessed: patch_vary_headers(response, ('Cookie',)) if modified or settings.SESSION_SAVE_EVERY_REQUEST: if request.session.get_expire_at_browser_close(): max_age = None expires = None else: max_age = request.session.get_expiry_age() expires_time = time.time() + max_age expires = cookie_date(expires_time) # Save the session data and refresh the client cookie. # Skip session save for 500 responses, refs #3881. if response.status_code != 500: request.session.save() # 將session保存到header中去 response["SESSION"] = request.session.session_key response.set_cookie(settings.SESSION_COOKIE_NAME, request.session.session_key, max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, path=settings.SESSION_COOKIE_PATH, secure=settings.SESSION_COOKIE_SECURE or None, httponly=settings.SESSION_COOKIE_HTTPONLY or None) return response
##在JavaScript中調用
代碼:
var session_id = ''; function get_session_id() { return session_id; } // callback: 登陸成功後回調用 function ossLogin(url, region, username, password, callback) { // var url = 'http://127.0.0.1:8000/auth/login/'; $.ajax({ type: 'POST', url: url, // login登陸成功後返回碼是302,用complete才能正確識別。 complete: function(xhr) { session_id = xhr.getResponseHeader('SESSION'); if (callback) { callback(session_id); } }, cache: false, data: { region: region, username: username, password: password, x: 223, y: 24 }, // 有這個才能讀取CORS_EXPOSE_HEADERS中的請求頭 xhrFields: { withCredentials: true } }); }
登陸成功後用get_session_id()
來獲取session_id,在後面的請求中加上SESSION
請求頭信息,下面給一個callback例子:
var callback = function(session_id) { console.log(session_id); $.ajax({ url: 'http://127.0.0.1:8000/do_sth', headers: { 'SESSION': session_id }, type: 'GET', cache: false, success: function(resp) { console.log(resp); } }) };