使用Angular 2进行Django会话认证

时间:2016-11-02 13:32:32

标签: django session angular basic-authentication

我一直在寻找使用Angular 2进行基于会话的身份验证。

我正在构建一个应用程序,它在后端有Django,在前端有Angular 2。为了简化流程,我正在尝试实现Django会话身份验证。

// Angular 2 authentication service
import { Injectable } from "@angular/core";
import { Headers, Http, Response } from "@angular/http";

import "rxjs/add/operator/toPromise";
import 'rxjs/add/operator/map'

import { AppSettings } from "../../app.settings";

@Injectable()
export class UserAuthService {
    private headers = new Headers({'Content-Type': 'application/json'});

    private loginUrl = `${AppSettings.BACKEND_URL}` + '/api/v1/users/login/';

    constructor(
        private http: Http
    ) { }

    login(username, password) {
        let data = {
            username: username,
            password: password
        };
        return this.http.post(this.loginUrl, data, this.headers)
            .map((response: Response) => response.json());
    }
}

# Django Login view
def login(self, request):
        username = request.data['username']
        password = request.data['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            serializer = self.serializer_class(user)
            return Response(serializer.data, status=status.HTTP_200_OK)
        raise AuthenticationFailed

我成功调用了后端API,我的login视图返回成功的响应。

登录后request.user也会更新,但是当我尝试使用Angular调用其他API或直接浏览Django时,其他API用户未登录。

1 个答案:

答案 0 :(得分:0)

这个问题的答案是将CSRF令牌附加到X-CSRF头,因为django使用X-CSRF令牌头来验证会话。

我并不完全记得我在哪里看过这个但是通过使用angular2-cookie并编写这样的自定义请求选项服务来实现这个目标

// Custom request options service
import { CookieService } from "angular2-cookie/services/cookies.service";
import { Headers, RequestOptions } from "@angular/http";
import { Injectable } from "@angular/core";

@Injectable()
export class CustomRequestOptionsService {

    constructor(
        private cookieService: CookieService
    ) { }

    defaultRequestOptions() {
        return new RequestOptions({
            headers: new Headers({
                'Content-Type': 'application/json',
            }),
            withCredentials: true
        });
    }

    authorizationRequestOptions() {
        return new RequestOptions({
            headers: new Headers({
                'Content-Type': 'application/json',
                'X-CSRFToken': this.cookieService.get('csrftoken')
            }),
            withCredentials: true
        });
    }
}

然后在您点击安全API的服务中使用它

// Officer service
import { Http, Response} from "@angular/http";
import { Injectable } from "@angular/core";
import "rxjs/add/operator/map";

// Services
import { CustomRequestOptionsService } from "../shared/custom-request-options.service";

@Injectable()
export class OfficerService {
    private officerDashboardUrl = `http://${process.env.API_URL}` + '/api/v1/officers/detail';

    constructor(
        private http: Http,
        private customRequestOptionService: CustomRequestOptionsService
    ) { }

    getOfficer(officerId: number) {
        return this.http.get(`${this.officerDashboardUrl}/${officerId}/`,
            this.customRequestOptionService.authorizationRequestOptions())
                   .toPromise()
                   .then((response: Response) => {
                       return response.json();
                   })
                   .catch((error: any) => {
                       return Promise.reject(error.message || error)
                   });
    }
}