Logout when closing window in Angular 4

2020-02-06 07:53发布

问题:

I have an Angular 4 applicaton and I want to call the logout function when the user close the page (window or tab of the browser).

This is my logout function :

    let currentUser: User = JSON.parse(localStorage.getItem('currentUser'));

    let headers = new Headers({ 'Authorization': 'Basic ' +  btoa(currentUser.login + ":" + currentUser.password),
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'access-control-allow-headers, access-control-allow-origin, content-type, authorization'
    });

    let opts = new RequestOptions();
    opts.headers = headers;


   return this.http.get(this.route + 'UserLogout', opts).map((response: Response) => response.json());
}

And in my app.component.ts, I have :

@HostListener('window:beforeunload', ['$event'])
beforeUnloadHander(event) {
    this.authenticationService.logoutOnClose().subscribe(res=> {
        localStorage.removeItem('currentUser');
    });

}

But the window is close and the request is never done. I think I need to do the request synchronously but I don't know how to do it.

Do you have an idea ?

EDIT I tried with jQuery :

 ngOnDestroy(){
    let currentUser: User = JSON.parse(localStorage.getItem('currentUser'));
    $.ajax({ url: 'myURL',
        beforeSend: function(request) {
            request.setRequestHeader("Authority", 'Basic ' +  btoa(currentUser.login + ":" + currentUser.password));
            request.setRequestHeader('Content-Type', 'application/json');
            request.setRequestHeader('Access-Control-Allow-Origin', '*');
            request.setRequestHeader('Access-Control-Allow-Headers', 'access-control-allow-headers, access-control-allow-origin, content-type, authorization');
        },
        type: 'GET',
        success: function (result) {
        alert('test');
        localStorage.removeItem('currentUser');
    }, async: false });
}

回答1:

I found how to do it. So, I would prefer avoid jQuery with Angular but like Sriram Jayaraman I didn't find anything else to fix my problem. But the functions @HostListener('window:beforeunload') and @HostListener('window:onunload') are not working.

So, in the ngOnInit of my app.component.ts, I added an event listener for beforeunload to the window and if the user is connected I call a function which make an ajax call.

This is my code :

ngOnInit() {
    let context = this;
    window.addEventListener("beforeunload", function (e) {
        let currentUser : User = JSON.parse(localStorage.getItem('currentUser'));
        if(currentUser){
            context.logoutOnClose();
        }
    });
}

logoutOnClose(){
    let currentUser: User = JSON.parse(localStorage.getItem('currentUser'));
    $.ajax({ url: 'myURL',
    beforeSend: function(request) {
        request.setRequestHeader("Authorization", 'Basic ' +  btoa(currentUser.login + ":" + currentUser.password));
        request.setRequestHeader('Content-Type', 'application/json');
        request.setRequestHeader('Access-Control-Allow-Origin', '*');
        request.setRequestHeader('Access-Control-Allow-Headers', 'access-control-allow-headers, access-control-allow-origin, content-type, authorization');
    },
    type: 'GET',
        success: function (result) {
        localStorage.removeItem('currentUser');
    },
    async: false });
}


回答2:

You can store your user and credentials in sessionStorage rather than localStorage. sessionStorage is removed whenever you close tab/browser, localStorage don't !



回答3:

Why would you disconnect your user on leaving is up to you. But if you want to do that, you have to adapt your code and logic to the framework, and not the other way around.

This means that you have to rewrite the user session when the user logs in again, or have a job that deletes unused sessions.

But in both ways, all you have to do is delete your localStorage/SessionStorage. If you do this, this will be transparent to the user, it's just how you manage it on your server that will change (but the user will have no idea)



回答4:

You can add any code that has to be executed to the OnDestroy function in your app.component.ts

export class AppComponent implements OnDestroy {
    ngOnDestroy(): void {
        this.authenticationService.logoutOnClose().subscribe(res=> {
            localStorage.removeItem('currentUser');
    });
}

However I'm not sure how this will handle the asynchronous call.. but it's worth trying.



回答5:

What you can do is that, make the API call synchronous using jQuery for this portion and make it synchronous as required. It is easy and does the job well.