Angular 2 http post重新加载页面,注销不会删除会话cookie

时间:2016-02-13 04:17:35

标签: cookies authorization angular

我有一个具有注销功能的Angular 2服务。从app组件调用该函数时,会导致整页刷新。当使用角度1项目时,我还没有经历过这种行为。如果我使用邮递员调用我的注销端点,则会删除会话cookie。如果我使用angular 2身份验证服务,则不会删除它。

服务

import {Injectable} from 'angular2/core';
import {User} from './user';
import {Headers, RequestOptions, Http, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import {Cookie} from '../extensions/cookies';

@Injectable()
export class AuthenticationService {

    constructor (private http: Http) {}

    private _prepTestHost = 'http://localhost:8000/';
    private _prepTestLoginUrl = this._prepTestHost + 'login/';
    private _prepTestLogoutUrl = this._prepTestHost + 'logout/';

    private _authenticated: boolean;

    getUser() {}

    isAuthenticated() {
        return this._authenticated;
    }

    setAuthenticated() {
        this._authenticated = true;
    }

    loginUser(username, password) : Observable<User> {
        let body = JSON.stringify({username, password});
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });

        return this.http.post(this._prepTestLoginUrl, body, options)
                                .map(res => <User> res.json(), this.setAuthenticated())
                                .catch(this.handleError)
    }

    logoutUser() : Observable<void> {
        let body = JSON.stringify({});
        let csrfcookie = Cookie.getCookie('csrftoken');
        let headers = new Headers({
            'X-CSRFToken': csrfcookie,
            'Content-Type': 'application/json'
        });
        let options = new RequestOptions({ headers: headers});
        return this.http.post(this._prepTestLogoutUrl, body, options)
                        .map(res => <void> res.json())
                        .catch(this.handleError);

    }

    private handleError (error: Response) {
        // in a real world app, we may send the server to some remote      logging infrastructure
        // instead of just logging it to the console
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }
}

应用组件

import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';

import {WelcomeCenterComponent} from './welcome-center/welcome-center.component';
import {AuthenticationService} from './authentication/authentication.service';
import {LoginModalComponent} from './authentication/login-modal.component';
import {BrowserXhr, HTTP_PROVIDERS} from "angular2/http";
import {CORSBrowserXHR} from './extensions/corsbrowserxhr';
import {provide} from "angular2/core";

@Component({
    selector: 'my-app',
    template: `
    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <div class="navbar-header">
          <a class="navbar-brand" href="#" [routerLink]="['WelcomeCenter']">Brand</a>
        </div>
        <ul class="nav navbar-nav navbar-right">
          <li *ngIf="!authenticated()">
            <a href="#" data-toggle="modal" data-target="#myModal">Login</a>
          </li>
          <li *ngIf="authenticated()">
            <a href="#" data-dismiss="modal" (click)="logout()">Logout</a>
          </li>
        </ul>
      </div>
    </nav>
    <router-outlet></router-outlet>
    <login-modal></login-modal>
    `,
    directives: [ROUTER_DIRECTIVES, LoginModalComponent],
    providers: [HTTP_PROVIDERS,
        provide(BrowserXhr, {useClass: CORSBrowserXHR}),
        AuthenticationService]
})
@RouteConfig([
    {
        path: '/welcome-center/...',
        name: 'WelcomeCenter',
        component: WelcomeCenterComponent,
        useAsDefault: true
    }
])
export class AppComponent {

    constructor(private _authenticationService: AuthenticationService) {}

    authenticated() {
        return this._authenticationService.isAuthenticated();
    }

    logout() {
        console.log("Logout button pressed");
        this._authenticationService.logoutUser().subscribe();
    }
}

设置withCredentials属性:

import {BrowserXhr, HTTP_PROVIDERS} from "angular2/http";
import {Injectable, provide} from "angular2/core";

@Injectable()
export class CORSBrowserXHR extends BrowserXhr{
    build(): any{
        var xhr:any = super.build();
        xhr.withCredentials = true;
        return xhr;
    }
}

2 个答案:

答案 0 :(得分:2)

我认为页面重新加载的原因是,在布局按钮上阻止时你不会阻止事件传播(你是一个带有&#39; href&的&#39; HTML元素&#39; #39;属性)。您可以使用&#39; return false&#39;在您的退出功能结束时或&#39; $ event.stopPropagation()&#39;。

有关详细信息,请参阅问题:

关于cookie问题,我使用跨域请求(CORS)。我认为你应该尝试设置为真实的&#39; withCredentials&#39;底层XHR对象的属性。有关详细信息,请参阅此问题:

答案 1 :(得分:0)

你可以做一些hacky但我不能想到另一种方式。

Cookie.setCookie(nameOfCookie, "", -1);

这将在注销时有效删除cookie。我很想知道是否有更好的方法!

我也不确定为什么你会得到任何类型的页面重新加载,我还没有体验到我已经完成的任何事情,希望其他人知道。