とDjango Rest Framework + Django CORSヘッダーを使用して、AngularJSで1ページのアプリケーションを開発しています。
私の問題は、バックエンドに接続したときに「csrftoken」Cookieがブラウザーに表示されないことです。
例:投稿を使用してログインしています。 「sessionid」Cookieは正しく取得されますが、「csrftoken」は表示されず、csrfトークンがないため拒否されるため、クライアントから適切な投稿を行うことができません。
フロント/バックエンドからのコードスニペット。これらは未完成のスニペットであるため、記述が不十分なコードにこだわらないでください。
class LoginView(APIView):
renderer_classes = (JSONPRenderer, JSONRenderer)
def post(self, request, format=None):
serializer = LoginSerializer(data=request.DATA)
if serializer.is_valid():
userAuth = authenticate(username=serializer.data['username'], password=serializer.data['password'])
if userAuth:
if userAuth.is_active:
login(request, userAuth)
loggedInUser = AuthUserProfile.objects.get(pk=1)
serializer = UserProfileSerializer(loggedInUser)
user = [serializer.data, {'isLogged': True}]
else:
user = {'isLogged': False}
return Response(user, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
.controller('LoginCtrl', ['$scope', '$http', 'uService', '$rootScope', function(scope, $http, User, rootScope) {
scope.login = function() {
var config = {
method: 'POST',
withCredentials: true,
url: rootScope.apiURL+'/user/login/',
data : scope.loginForm
};
$http(config)
.success(function(data, status, headers, config) {
if (status == 200) {
console.log(data[0]); //Test code
// succefull login
User.isLogged = true;
User.username = data.username;
}
else {
console.log(data); //Test code
User.isLogged = false;
User.username = '';
}
})
.error(function(data, status, headers, config) {
console.log('Testing console error');
User.isLogged = false;
User.username = '';
});
};
}]);
良いヒント/アイデア/例はありますか?
CORSおよびCSRF保護を使用してサブドメインBのDjango JSON(REST)APIと通信するサブドメインAのAngularJSシングルページWebアプリケーション
現在、同様の設定に取り組んでおり、CSRF保護と組み合わせてCORSを適切に機能させるために戦っていたので、ここで自分の学習を共有したいと考えました。
Setup-SPAとAPIは両方とも同じドメインの異なるサブドメインにあります。
AngularJSアプリは、Django APIアプリと同じプロジェクトのDjangoアプリを通じて提供され、CSRF Cookieを設定します。たとえば、次も参照してください 1つのDjangoプロジェクトから複数のWebサイトを実行する方法
Django API App-CORSおよびCSRF保護を機能させるには、APIバックエンドで次の操作を行う必要がありました。
このアプリのsettings.py(Djangoプロジェクトのsettings.pyの拡張):
INSTALLED_APPS = ( ... 'corsheaders', ... ) MIDDLEWARE_CLASSES = ( ... 'Django.middleware.csrf.CsrfViewMiddleware', ... 'corsheaders.middleware.CorsMiddleware', )
GitHubのDjango CORSヘッダー も参照してください。
CORS_Origin_WHITELIST = [ ... 'app.mydomain.com', ... ]
CORS_ALLOW_CREDENTIALS = True
JSON APIリクエストを処理するビューにensure_csrf_cookieデコレータを追加します。
from Django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def myResource(request): ...
AngularJS用のDjangoアプリ-AngularJSアプリは、同じプロジェクトのDjangoアプリを介して提供されます。このDjangoアプリは、CSRF Cookieを設定するように設定されています。 CookieからのCSRFトークンは、APIへの要求に使用されます(したがって、同じDjangoプロジェクトの一部として実行されます)。
AngularJSアプリケーションに関連するほとんどすべてのファイルは、Djangoの観点から見ると静的ファイルであることに注意してください。 Djangoアプリは、cookieを設定するためにindex.htmlを提供するだけです。
このアプリのsettings.py(Djangoプロジェクトのsettings.pyの拡張子)で、サブドメインでも使用できるようにCSRF_COOKIE_DOMAINを設定します。
CSRF_COOKIE_DOMAIN = ".mydomain.com"
Views.pyでは、AngularJS index.htmlファイルをレンダリングするだけで、再度ensure_csrf_cookieデコレータを使用します。
from Django.shortcuts import render from Django.views.decorators.csrf import ensure_csrf_cookie # Create your views here. @ensure_csrf_cookie def index(request): return render(request, 'index.html')
AngularJSを使用してAPIにリクエストを送信-AngularJSアプリの設定で、次の$ httpProviderのデフォルトを設定します。
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; $httpProvider.defaults.withCredentials = true;
繰り返しますが、withCredentialsに注意してください。これにより、CSRF Cookieがリクエストで使用されます。
以下に、AngularJS $ httpサービスとJQueryを使用してAPIにリクエストを送信する方法を示します。
$http.post("http://api.mydomain.com/myresource", { field1 : ..., ... fieldN : ... }, { headers : { "x-csrftoken" : $cookies.csrftoken } });
ngCookiesモジュール も参照してください。
JQuery(1.11.0)の使用:
$.ajax("http://api.mydomain.com/myresource", { type: 'POST', dataType : 'json', beforeSend : function(jqXHR, settings) { jqXHR.setRequestHeader("x-csrftoken", get_the_csrf_token_from_cookie()); }, cache : false, contentType : "application/json; charset=UTF-8", data : JSON.stringify({ field1 : ..., ... fieldN : ... }), xhrFields: { withCredentials: true } });
これがお役に立てば幸いです!!
ドキュメントから直接 https://docs.djangoproject.com/en/1.9/ref/csrf/#ajax
ビューがcsrf_tokenテンプレートタグを含むテンプレートをレンダリングしていない場合、DjangoはCSRFトークンCookieを設定しない可能性があります。これは、フォームがページに動的に追加される場合に一般的です。 、Djangoは、Cookieの設定を強制するビューデコレータを提供します:ensure_csrf_cookie()。
アプリケーションは単一ページのアプリケーションであるため、ensure_csrf_cookie()
を最初のページの読み込みを担当するビューに追加できます。
このソリューションの小さな更新。
AngularJS 1.2.10以降では、クライアントのリクエストタイプごとにCSRF Cookieを設定する必要があります。
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.put['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers['delete']['X-CSRFToken'] = $cookies.csrftoken;
これは、1.2.9と1.2.10の間で発生した次の変更によるものです https://github.com/cironunes/angular.js/commit/781287473bc2e8ee67078c05b76242124dd43376
これが誰かを助けることを願っています!
非常に多くの検索の後、私はこのソリューションに着陸し、その作業はローカルシステム上およびライブWebファクションサーバー上で私を形作りますこれはDjangoユーザー向けの私のソリューションプロジェクトにあるApacheフォルダに移動してから、ビンで見つけます
<IfModule mod_headers.c>
SetEnvIf Origin (.*) AccessControlAllowOrigin=$1
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header set Access-Control-Allow-Credentials true
</IfModule>
次に、angular js appに配置する必要がありました
angular.module('app', ['ngCookies'])
.config([
'$httpProvider',
'$interpolateProvider',
function($httpProvider, $interpolateProvider, $scope, $http) {
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
}]).
run([
'$http',
'$cookies',
function($http, $cookies) {
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
}]);