2016-02-13 121 views
2

我有一個具有註銷功能的Angular 2服務。當從應用程序組件調用該函數時,會導致整個頁面刷新。當使用角度1項目時,我沒有經歷過這種行爲。如果我用postman調用我的註銷端點,會話cookie將被刪除。如果我使用我的角度2認證服務,它不會被刪除。Angular 2 http post重新加載頁面,註銷不會刪除會話cookie

服務

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; 
    } 
} 
+0

是角拋頁面上的任何錯誤刷新?如果是的,請發表似乎同樣的問題,我曾經面臨可能會幫助你生病。 –

+0

@PardeepJain似乎沒有錯誤。我的服務器響應狀態200,會話在服務器上被銷燬。 – MichaelB

+0

ohh好吧...我想在你的'logoutUser'中有一個錯誤是你''.map'返回'null或void'的觀察值,你訂閱null。可能是這個產生的影響一定程度上再次發生。 –

回答

2

我認爲頁面重新加載是因爲您在佈局按鈕上禁用事件傳播(您是'a''具有'href'屬性的HTML元素')時不會阻止事件傳播。您可以在註銷功能結束時使用'return false'或'$ event.stopPropagation()'。

詳情請參見問題:關於cookie的問題

,我這些你使用跨域請求(CORS)。我認爲你應該嘗試在底層的XHR對象上設置爲'withCredentials'屬性。看到這個問題的更多細節:

+0

這是導致頁面重新加載的'href =「#」'。這掩蓋了我現在正在研究的一個錯誤。 – MichaelB

+0

我已經設置了withCredentials屬性,我已經添加了上面的代碼。 ' – MichaelB

0

你可以做些什麼樣的哈克,但我想不出的另一種方式。

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

這會在註銷時有效地刪除cookie。我很想知道是否有更好的方法!

我也不確定爲什麼你會得到任何類型的頁面重新加載,我還沒有體驗到我所做的任何事情,希望別人會知道。

+0

我可以知道你發佈的語法是JavaScript的語法來刪除Cookie嗎? –

+0

@PardeepJain它來自angular2的擴展https://www.npmjs.com/package/ng2-cookies,我認爲他使用它以及他有相同的語法。 –

+0

@MorganG刪除'href =「#」'似乎也讓處理清除sessionid cookie的代碼執行,並正確地刪除cookie。我從來沒有必須用角度1應用程序手動刪除sessionid cookie,現在它在角度2中似乎是相同的。感謝您的幫助。 Thierry Templier的回答是正確的。 – MichaelB