headers - no ''access-control-allow-origin'' header is present on the requested resource django
AngularJS+Django Rest Framework+CORS(la cookie CSRF no aparece en el cliente) (5)
Así que encontré mi propia solución a esto, parece funcionar muy bien.
Estos son los nuevos fragmentos de mi código:
API de inicio de sesión LoginView (se agregó un decorador forzando que el token csrf se agregue al cuerpo)
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 lado del cliente (agregue el token al encabezado de la solicitud)
$http.defaults.headers.post[''X-CSRFToken''] = $cookies.csrftoken;
Archivo de configuración del lado del servidor (Específicamente para django-cors-headers)
Los primeros 5 se agregan por defecto, pero debe agregar "X-CSRFToken" para permitir dicho encabezado desde el cliente a la API usando CORS, de lo contrario la publicación será denegada.
CORS_ALLOW_HEADERS = (
''x-requested-with'',
''content-type'',
''accept'',
''origin'',
''authorization'',
''X-CSRFToken''
)
¡Eso es!
Estoy desarrollando una aplicación de 1 página en AngularJS utilizando y Django Rest Framework + Django CORS Headers.
Mi problema es que la cookie "csrftoken" nunca aparece en mi navegador cuando me he puesto en contacto con el servidor.
Por ejemplo: estoy iniciando sesión usando una publicación. Recibo la cookie "sessionid" correctamente, pero la "csrftoken" nunca aparece y, por lo tanto, no puedo hacer publicaciones correctas de mi cliente, ya que me negarán debido a la falta del token csrf.
- He analizado los encabezados de respuesta de la API y el csrftoken no está allí.
- He buscado directamente en el resto del navegador API y se muestra bien allí.
- Solo para señalar, puedo hacer mi primer POST para iniciar sesión ya que Django Rest Framework solo fuerza a CSRF para usuarios autenticados. Si trato de volver a iniciar sesión, fallará ya que el "sessionid" -cookie presente.
- No estoy interesado en eludir la protección CSRF como sugieren algunas publicaciones en stackoverflow.
Algunos fragmentos de código de front / backend. Estos son fragmentos sin terminar, así que no te obsesiones con el código mal escrito.
Backend API LoginView
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)
Controlador de inicio de sesión AngularJS del lado del cliente
.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 = '''';
});
};
}]);
¿Alguien con buenos consejos / ideas / ejemplos?
Después de tanta búsqueda que obtuve esta solución y su trabajo me formó en el sistema local y también en el servidor de facciones web en vivo, esta es mi solución para los usuarios de Django , por favor diríjase a su carpeta apache ubicada en el proyecto y luego en la bandeja encontrará
httpd.conf o su configuración de servidor para php u otros usuarios (generalmente ubicados en un archivo * .conf, como httpd.conf o apache.conf), o dentro de .htaccess. entonces simplemente agrega este código
<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>
luego en la aplicación de js angular solo necesitabas colocar
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;
}]);
Funcionó para mí en la plataforma Django Angularjs.
Directamente desde los documentos https://docs.djangoproject.com/en/1.9/ref/csrf/#ajax
Si su vista no muestra una plantilla que contenga la etiqueta de plantilla csrf_token, Django podría no configurar la cookie de token CSRF. Esto es común en los casos en que los formularios se agregan dinámicamente a la página. Para abordar este caso, Django proporciona un decorador de vista que fuerza la configuración de la cookie: ensure_csrf_cookie ().
Como su aplicación es de una sola página, puede agregar ensure_csrf_cookie()
a la vista que es responsable de la carga de la página inicial.
Una pequeña actualización de esta solución.
Desde AngularJS 1.2.10, debe configurar la cookie CSRF para cada tipo de solicitud en el cliente:
$http.defaults.headers.post[''X-CSRFToken''] = $cookies.csrftoken;
$http.defaults.headers.put[''X-CSRFToken''] = $cookies.csrftoken;
$http.defaults.headers[''delete''][''X-CSRFToken''] = $cookies.csrftoken;
Esto debido al siguiente cambio que ocurrió entre 1.2.9 y 1.2.10 https://github.com/cironunes/angular.js/commit/781287473bc2e8ee67078c05b76242124dd43376
¡Espero que esto ayude a alguien!
Aplicación web de una sola página de AngularJS en el subdominio A, hablando con una API de Django JSON (REST) en el subdominio B utilizando la protección CORS y CSRF
Como actualmente estoy trabajando en una configuración similar y estaba luchando para hacer que CORS funcione correctamente en combinación con la protección CSRF, quería compartir mis propios aprendizajes aquí.
Configuración : el SPA y la API se encuentran en diferentes subdominios del mismo dominio:
- AngularJS (1.2.14) Aplicación web de una sola página en el subdominio app.midominio.com
- La aplicación Django (1.6.2) implementa una API JSON REST en el subdominio api.midominio.com
La aplicación AngularJS se sirve a través de una aplicación Django en el mismo proyecto que la aplicación Django API, de modo que establece una cookie CSRF. Ver, por ejemplo, también Cómo ejecutar varios sitios web desde un proyecto de Django
Aplicación Django API : para que funcione la protección CORS y CSRF, necesitaba hacer lo siguiente en el backend API.
En settings.py para esta aplicación (una extensión del proyecto Django settings.py):
- Agregue la aplicación corsheaders y el middleware y el middleware CSRF:
INSTALLED_APPS = ( ... ''corsheaders'', ... ) MIDDLEWARE_CLASSES = ( ... ''django.middleware.csrf.CsrfViewMiddleware'', ... ''corsheaders.middleware.CorsMiddleware'', )
Ver también encabezados Django CORS en GitHub
- Agregue el dominio de la aplicación web SPA a CORS_ORIGIN_WHITELIST
CORS_ORIGIN_WHITELIST = [ ... ''app.mydomain.com'', ... ]
- Establezca CORS_ALLOW_CREDENTIALS en True. Esto es importante, si no haces esto, no se enviará una cookie CSRF con la solicitud
CORS_ALLOW_CREDENTIALS = True
Agregue el decorador ensure_csrf_cookie a sus vistas manejando las solicitudes API JSON:
from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def myResource(request): ...
Aplicación Django para AngularJS : la aplicación AngularJS se sirve a través de una aplicación Django en el mismo proyecto. Esta aplicación Django está configurada para configurar una cookie CSRF. El token CSRF de la cookie se usa para solicitudes a la API (que, por lo tanto, se ejecuta como parte del mismo proyecto Django).
Tenga en cuenta que casi todos los archivos relacionados con la aplicación AngularJS son solo archivos estáticos desde la perspectiva de Django. La aplicación Django solo necesita servir el index.html para configurar la cookie.
En settings.py para esta aplicación (una vez más una extensión del proyecto Django settings.py), configure el CSRF_COOKIE_DOMAIN de manera que los subdominios también puedan usarlos:
CSRF_COOKIE_DOMAIN = ".midominio.com"
En views.py, solo necesito renderizar el archivo AngularJS index.html, nuevamente usando el decorador 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'')
Envío de solicitudes a la API mediante AngularJS : en la configuración de la aplicación AngularJS configure los siguientes valores predeterminados $ httpProvider:
$httpProvider.defaults.xsrfCookieName = ''csrftoken''; $httpProvider.defaults.xsrfHeaderName = ''X-CSRFToken''; $httpProvider.defaults.withCredentials = true;
De nuevo, tome nota de withCredentials, esto asegura que la cookie CSRF se usa en la solicitud.
A continuación, le muestro cómo puede realizar solicitudes a la API mediante el servicio AngularJS $ http y JQuery:
$http.post("http://api.mydomain.com/myresource", { field1 : ..., ... fieldN : ... }, { headers : { "x-csrftoken" : $cookies.csrftoken } });
También vea el módulo ngCookies .
Usando 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 } });
¡¡Espero que esto ayude!!