简体   繁体   中英

Angular2 Http Call not firing

Context :

Following several tutorials, I am testing authentication with Angular2 and JWT. I come with a component and a service :

app.component.ts
user.service.ts

App component (and template) contains the subscription to an observable that shows the user logged in status. The Observable item is kept in the user service, and changes (fine) when user logs in and out.

The authentication token is written in "localStorage" as "auth_token". It contains a validity value (time) that should force the user to login again after a time.

What I'd like to do is to CHECK the token validity on app init. First, I tried to do it from the user.service CONSTRUCTOR, then (fail), I tried to do it from ngOnInit in the app.component, then (fail again), I tried to do it on event call (click on a button) from the app component, but fails again!

Some shortened code :

//app.component.html
//...
    <a md-button class="app-icon-button" aria-label="checklogin" (click)="checkLogin()">
        <md-icon svgIcon="check"></md-icon>
    </a>
//...

//app.component.ts
//...
    checkLogin(){
        console.log('CHECK LOGIN FUNCTION');
        let token = localStorage.getItem('auth_token');
        if(token){
            console.log('TOKEN FOUND');
            this.userService.checkToken(token);
        }else{
            console.log('NO TOKEN FOUND');
        }
    }
//...

//user.service.ts
//...
    checkToken(token){
        console.log('CHECK TOKEN FUNCTION');
        console.log('TOKEN : '+token);
        let headers = new Headers();
        headers.append('Content-Type','application/json');
        return this.http
            .post(
                '/url/script.php',
                JSON.stringify(token),
                { headers }
            )
            .map(res => res.json())
            .map((res) => {
                console.log('SCRIPT RESULT : ');
                if(res.valid){
                    console.log('TOKEN IS VALID');
                    return true;
                }else{
                    console.log('TOKEN NOT VALID');
                    return false;
                }
            });
    }
//...

I did skip the observable part, and subscription.

Problem :

The problem actually is that the app NEVER CALLS the script!

When I do click on the "checkLogin" button (when token exists),

console shows 'CHECK LOGIN FUNCTION',
console shows 'TOKEN FOUND',
console shows 'CHECK TOKEN FUNCTION',
console shows 'TOKEN : '****************************** (token),

But it never shows 'SCRIPT RESULT', and when using firebug to check if the http call is done, there is NO CALL to the script.php. Looks like the this.http part is just ignored...

Thanks for reading/help

Ajax call's which use Observables will work only if you have an subscriber .

So you need to subscribe to that Observable . It is an Angular 2 feature. When you don't subscribe the Observable , it will never make that call.

And also you don't need to return anything from the subscriber, because you actually can't return anything.

this.userService.checkToken(token).subscribe((res) => {
   console.log('SCRIPT RESULT : ');
   if(res.valid) {
      console.log('TOKEN IS VALID');          
   } else {
      console.log('TOKEN NOT VALID');
   }
});

checkToken(token){
   console.log('CHECK TOKEN FUNCTION');
   console.log('TOKEN : '+token);
   let headers = new Headers();
   headers.append('Content-Type','application/json');
   return this.http
       .post(
           '/url/script.php',
           JSON.stringify(token),
           { headers }
       )
       .map(res => res.json());           
}

Service starts working when subscription used only when consumer subscribe to output result, using .subscribe method.

You need: this.userService.checkToken(token).subscribe()

Your checkToken() method is returning an Observable that you need to subsrcibe to. An observable will never to execute unless it's subscribed to.

checkLogin(){
        console.log('CHECK LOGIN FUNCTION');
        let token = localStorage.getItem('auth_token');
        if(token){
            console.log('TOKEN FOUND');
            this.userService.checkToken(token).subscribe(result => {
               console.log(result); 
            }),
            error => { 
               console.log(error); 
            });
        } else {
            console.log('NO TOKEN FOUND');
        }
    }

Have You tried using Postman and try to call function you need?

Also, why do You need to validate a token if angular2-jwt can do this for You?

You can do just like this:

install angular2-jwt with npm .

Include in app.module.ts :

import { AUTH_PROVIDERS } from 'angular2-jwt';

add to providers:

providers: [
    AUTH_PROVIDERS,
],

and for example auth.service.ts looks like this:

import { Injectable, Inject }                                               from '@angular/core';
import { Http, Response, Headers, RequestOptions, RequestMethod }           from '@angular/http';
import { Router }                                                           from '@angular/router';

import { Observable }                                                       from 'rxjs/Observable';
import { Configuration }                                                    from '../../app.config';

import { RegisterViewModel }                                                from '../../model/viewModel/registerViewModel';
import { LoginViewModel }                                                   from '../../model/viewModel/loginViewModel';

import { tokenNotExpired, AuthHttp }                                        from 'angular2-jwt';

@Injectable()
export class AuthService {

private actionUrl: string; 

constructor(private _http: Http, private _config: Configuration, private _router: Router, private _authHttp: AuthHttp){
    this.actionUrl = _config.apiUrl;
}

register(user: RegisterViewModel){
    let headers = new Headers({ 'Content-Type': 'application/json' });
    //Admin in this system can only register users. that is why auth
    return this._authHttp.post(this.actionUrl + '/Account/Register', JSON.stringify(user), { headers : headers })
        .do(response => {
            console.log(response.toString());
        });
}

login(user: LoginViewModel) {
    let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
    return this._http.post('http://localhost:56181/api/token', "username=" + user.userName + "&password=" + user.password + "&userId=" + user.userId, { headers : headers })
        .do(response => {
            if(response){
                let authResult = response.json();
                this.setUser(authResult);
                this._router.navigate(['']);
            }
        });
}

public isAuthenticated(): boolean {
    //angular2-jwt has this function to check if token is valid
    return tokenNotExpired();
}

private setUser(authResult: any): void {
    localStorage.setItem('id_token', authResult.id_token);
}

public logout(): void {
    localStorage.removeItem('id_token');
    this._router.navigate(['']);
}

}

also remember that angular2-jwt has default name for token in localstorage as id_token or else you will have to use angular2-jwt help class to specify other token name.

You can check if it is working by simply doing this:

in app.component.ts :

export class AppComponent { 
constructor(private _auth: AuthService){
}
}

and in app.component.html :

 <li>
 <a class="nav-link" [routerLink]="['/login']" *ngIf="!_auth.isAuthenticated()">Login</a>
 </li>
 <li>
 <a class="nav-link" (click)="_auth.logout()" *ngIf="_auth.isAuthenticated()">Log Out</a>
 </li>

also You can read a little bit documentation about it in:

https://auth0.com/blog/introducing-angular2-jwt-a-library-for-angular2-authentication/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM