2016-02-13 123 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