背景:
在几个教程之后,我正在使用Angular2和JWT测试身份验证。我带来了一个组件和服务:
app.component.ts
user.service.ts
应用程序组件(和模板)包含对显示用户登录状态的observable的订阅。 Observable项保存在用户服务中,并在用户登录和注销时更改(正常)。
身份验证令牌写在" localStorage" as" auth_token"。它包含一个有效值(时间),应强制用户在一段时间后再次登录。
我想做的是在app init上检查令牌有效性。首先,我尝试从user.service CONSTRUCTOR,然后(失败),我尝试从app.component中的ngOnInit,然后(再次失败),我试图在事件调用(点击一个按钮)来自应用程序组件,但再次失败!
一些缩短的代码:
//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;
}
});
}
//...
我确实跳过了可观察的部分和订阅。
问题:
问题实际上是应用程序永远不会调用脚本!
当我点击&#34; checkLogin&#34;按钮(当存在令牌时),
console shows 'CHECK LOGIN FUNCTION',
console shows 'TOKEN FOUND',
console shows 'CHECK TOKEN FUNCTION',
console shows 'TOKEN : '****************************** (token),
但它从未显示过“SCRIPT RESULT&#39;”, 当使用firebug检查http调用是否完成时,对script.php没有任何调用。貌似this.http部分只是被忽略了......
感谢您阅读/帮助
答案 0 :(得分:1)
使用Observables
的Ajax调用仅在您拥有subscriber
时才有效。
所以你需要subscribe
到那个Observable
。这是Angular 2
功能。当您没有订阅Observable
时,它将永远不会拨打该电话。
而且您也不需要从订阅者处返回任何内容,因为您实际上无法返回任何内容。
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());
}
答案 1 :(得分:1)
当订阅仅在消费者使用.subscribe
方法订阅输出结果时使用时,服务才开始工作。
您需要:this.userService.checkToken(token).subscribe()
答案 2 :(得分:1)
您的checkToken()
方法返回Observable
所需的subsrcibe
。除非它订阅,否则观察者永远不会执行。
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');
}
}
答案 3 :(得分:1)
您是否尝试使用Postman
并尝试调用所需的功能?
另外,如果angular2-jwt
可以为您执行此操作,为什么需要验证令牌?
你可以这样做:
使用angular2-jwt
安装npm
。
加入app.module.ts
:
import { AUTH_PROVIDERS } from 'angular2-jwt';
添加到提供者:
providers: [
AUTH_PROVIDERS,
],
例如auth.service.ts
如下所示:
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(['']);
}
}
还要记住angular2-jwt
localstorage
中的令牌默认名称为id_token
,否则您必须使用angular2-jwt
帮助类来指定其他令牌名称。
您可以通过以下方式检查它是否正常工作:
app.component.ts
中的:
export class AppComponent {
constructor(private _auth: AuthService){
}
}
和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>
你也可以在以下网址阅读一些文档:
https://auth0.com/blog/introducing-angular2-jwt-a-library-for-angular2-authentication/