AngularJS + Django Rest Framework + CORS (CSRF Cookie가 클라이언트에 표시되지 않음)
Angular에서 1페이지짜리 어플리케이션을 개발하고 있습니다.JS와 Django Rest Framework + Django CORS 헤더를 사용합니다.
문제는 백엔드에 접속해도 브라우저에 csrftoken 쿠키가 표시되지 않는다는 것입니다.
예를 들어 다음과 같습니다.게시물을 사용하여 로그인을 하고 있습니다."sessionid" cookie는 정상적으로 표시되지만 "csrftoken"은 표시되지 않기 때문에 csrf 토큰이 없기 때문에 클라이언트에서 적절한 투고를 할 수 없습니다.
- API에서 응답 헤더를 분석했는데 csrftoken이 없습니다.
- 나머지 API 브라우저에서 직접 확인해보니 잘 나오네요.
- 참고로 Django Rest Framework는 인증된 사용자에게만 CSRF를 강제하기 때문에 첫 POST 로그인을 할 수 있습니다.다시 로그인하려고 하면 "sessionid" 쿠키가 나타나기 때문에 실패합니다.
- stackoverflow의 일부 게시물이 시사하는 바와 같이 CSRF 보호를 우회하는 데는 관여하지 않습니다.
전면/후면에서 코드 조각이 몇 개 있습니다.이것들은 지워지지 않은 단편들이니, 서투르게 쓰여진 코드에 집착하지 마세요.
백엔드 API Login View
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)
클라이언트 측 각도JS 로그인 컨트롤러
.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 = '';
});
};
}]);
좋은 팁/아이디어/예시를 가지고 계신 분?
서브 도메인 A의 AngularJS 싱글 페이지 웹 애플리케이션, CORS 및 CSRF 보호를 사용한 서브 도메인B의 Django JSON(REST) API와의 통신
저는 현재 비슷한 셋업을 하고 있고, CSRF 보호와 함께 CORS를 제대로 작동시키기 위해 노력하고 있었기 때문에, 여기에서 제 자신의 학습 내용을 공유하고 싶었습니다.
셋업 - SPA와 API는 모두 같은 도메인의 다른 서브도메인 상에 있습니다.
- AngularJS(1.2.14) 서브도메인 app.mydomain.com의 싱글페이지 웹 어플리케이션
- Django App(1.6.2)은 서브도메인 api.mydomain.com에 JSON REST API를 구현합니다.
앵귤러JS 앱은 장고 API APP와 동일한 프로젝트에서 장고 앱을 통해 CSRF Cookie를 설정합니다.예를 들어 하나의 Django 프로젝트에서 여러 웹 사이트를 실행하는 방법을 참조하십시오.
Django API App - CORS 및 CSRF 보호 기능을 사용하려면 API 백엔드에서 다음 작업을 수행해야 했습니다.
settings.py에서 이 앱(Django 프로젝트 설정 확장)을 참조하십시오.py):
- corsheaders 앱과 미들웨어 및 CSRF 미들웨어를 추가합니다.
INSTALLED_APPS = ( ... 'corsheaders', ... ) MIDDLEWARE_CLASSES = ( ... 'django.middleware.csrf.CsrfViewMiddleware', ... 'corsheaders.middleware.CorsMiddleware', )
GitHub의 Django CORS 헤더도 참조하십시오.
- SPA WebApp 도메인을 CORS_ORIGIN_WHITelist에 추가합니다.
CORS_ORIGIN_WHITELIST = [ ... 'app.mydomain.com', ... ]
- CORS_ALLOW_CREDEN셜을 True로 설정합니다.이것은 중요합니다.이렇게 하지 않으면 요청과 함께 CSRF 쿠키가 전송되지 않습니다.
CORS_ALLOW_CREDICENTS = True
JSON API 요청을 처리하는 뷰에 sure_csrf_cookie 데코레이터를 추가합니다.
from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def myResource(request): ...
각진 장고 앱JS - 각도JS 앱은 같은 프로젝트에서 장고 앱을 통해 제공됩니다.CSRF Cookie를 설정하도록 설정된 Django App입니다.cookie로부터의 CSRF 토큰은 API(따라서 같은 Django 프로젝트의 일부로 실행)에 대한 요구에 사용됩니다.
Angular와 관련된 거의 모든 파일은JS 애플리케이션은 장고의 관점에서 보면 정적 파일일 뿐입니다.Django App은 쿠키를 설정하기 위해 index.html만 제공하면 됩니다.
이 앱의 settings.py(또한 Django 프로젝트 settings.py의 확장)에서 CSRF_COOKIE_DOMAIN을 설정하여 하위 도메인도 사용할 수 있도록 합니다.
CSRF_COOKIE_DOMAIN = ".mydomain.com"
views.py에서는 Angular만 렌더링하면 됩니다.다시 sure_csrf_cookie 데코레이터를 사용하여 JS index.html 파일을 만듭니다.
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')
Angular를 사용하여 API에 요청 전송JS - 각도 내JS App 구성은 다음과 같은 $httpProvider 기본값을 설정합니다.
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; $httpProvider.defaults.withCredentials = true;
다시 한 번 withCredentials에 주의해 주십시오.이것에 의해, 요구에 CSRF Cookie 가 확실히 사용됩니다.
아래는 Angular를 사용하여 api에 요청을 하는 방법을 보여 줍니다.JS $http 서비스 및 JQuery:
$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/ #docs에서 직접 다운로드
뷰가 csrf_token 템플릿태그를 포함하는 템플릿을 렌더링하지 않으면 Django는 CSRF 토큰 쿠키를 설정하지 않을 수 있습니다.이것은 양식이 페이지에 동적으로 추가되는 경우에 일반적입니다.이 문제에 대처하기 위해 Django는 cookie 설정을 강제하는 뷰 데코레이터를 제공합니다.sure_csrf_cookie().
에, 「」를 할 수 .ensure_csrf_cookie()
초기 페이지 로드의 원인이 되는 뷰로 이동합니다.
그래서 이 문제에 대한 저만의 해결책을 찾았고, 잘 된 것 같아요.
다음은 내 코드의 새로운 조각입니다.
Backend API LoginView(csrf 토큰을 본문에 강제로 추가)
class LoginView(APIView):
renderer_classes = (JSONPRenderer, JSONRenderer)
@method_decorator(ensure_csrf_cookie)
def post(self, request, format=None):
c = {}
c.update(csrf(request))
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)
AngularJS 클라이언트 측(요청 헤더에 토큰 추가)
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
서버측 설정 파일(django-cors-headers 전용)
처음 5개는 기본적으로 추가되지만 클라이언트로부터 CORS를 사용하여 API로의 헤더를 허용하려면 "X-CSRFToken"을 추가해야 합니다.그렇지 않으면 투고는 거부됩니다.
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'X-CSRFToken'
)
바로 그거야!
이 솔루션의 작은 업데이트입니다.
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
이게 누군가에게 도움이 되길 바라!
So Much Search i가 이 솔루션에 도달한 후 로컬 시스템과 라이브 웹 파벌 서버에서도 이것이 나의 솔루션입니다.프로젝트에 있는 apache 폴더로 가서 bin을 찾으십시오.
httpd.conf 또는 php 또는 기타 사용자용 서버 설정(보통 httpd.conf 또는 apache.conf 등의 *.conf 파일에 위치) 또는 .htaccess 내에 있습니다.그럼 이 코드를 추가해 주세요.
<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 앱에 배치하면 됩니다.
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;
}]);
Django Angularjs 플랫폼에서 작동했습니다.
https://gist.github.com/mlynch/be92735ce4c547bd45f6
언급URL : https://stackoverflow.com/questions/17931158/angularjs-django-rest-framework-cors-csrf-cookie-not-showing-up-in-client
'sourcecode' 카테고리의 다른 글
VB의 여러 줄 문자열.그물 (0) | 2023.04.08 |
---|---|
PHP 프레임워크 여부(Cake PHP) (0) | 2023.04.03 |
TypeScript, React, Eslint 및 단순 Arrow 함수 컴포넌트 문제 (0) | 2023.04.03 |
angular 2 라우터를 사용하여 현재 루트를 새로고침하는 방법 (0) | 2023.04.03 |
JQuery $.ajax() post - Java 서블릿의 데이터 (0) | 2023.04.03 |