Angular2 - 如何最好地处理过期的身份验证令牌?

Don*_*ers 15 angular2-routing angular2-jwt angular

我正在使用Angular 2.1.2.

我有一个身份验证令牌(使用angular2-jwt),如果它到期,我的webApi调用失败,出现401错误.我正在寻找一个解决方案,用户不会丢失任何输入数据.

我可以抓住这个401并用登录打开一个模态.然后用户登录,模态消失,他们看到他们的输入屏幕.但是,失败的请求显示错误,因此我需要重新处理请求.如果是路由器导航,则初始数据未加载.

我可以重新加载页面,但如果我router.navigate到同一页面,它似乎并没有真正重新加载页面.我不想在单页面应用上进行整页重新加载.有没有办法强制router.navigate运行,即使它是当前页面?

重新导航仍然是一个问题,因为我会丢失任何未保存的新输入数据.

理想情况下,请求只是"暂停",直到用户从模态登录.我还没有找到实现这个的方法.

有任何想法吗?有最好的做法吗?

yux*_*ang 5

通常我会提供HttpService自己而不是Http直接使用.因此,根据您的要求,我可以提供自己的get()方法来链接身份验证,然后再发送任何真实的HTTP请求.

这是服务:

@Injectable()
class HttpService {
  constructor(private http: Http, private auth: Authentication) {}

  public get(url: string): Observable<Response> {
    return this.auth.authenticate().flatMap(authenticated => {
      if (authenticated) {
        return this.http.get(url);
      }
      else {
        return Observable.throw('Unable to re-authenticate');
      }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是调用服务的组件:

@Component({
  selector: 'my-app',
  template: `<h1>Hello {{name}}</h1>
  <button (click)="doSomething()">Do Something</button>

  <div [hidden]="!auth.showModal">
  <p>Do you confirm to log in?</p>
  <button (click)="yes()">Yes</button><button (click)="no()">No</button>
  </div>
  `,
})
export class AppComponent {
   name = 'Angular';

   constructor(private httpSvc: HttpService, public auth: Authentication) {}

   ngOnInit() {
   }

   doSomething() {
     let a = this.httpSvc.get('hello.json').subscribe(() => {
       alert('Data retrieved!');
     }, err => {
       alert(err);
     });
   }

   yes() {
    this.auth.confirm.emit(true);
   }

   no() {
     this.auth.confirm.emit(false);
   }
}
Run Code Online (Sandbox Code Playgroud)

通过链接observable,Authentication服务确定是否中断正常流程以显示模态(虽然目前只与App组件一起使用,但它当然可以单独实现).一旦从对话框收到肯定答复,服务就可以恢复流程.

class Authentication {
  public needsAuthentication = true;
  public showModal = false;
  public confirm = new EventEmitter<boolean>();

  public authenticate(): Observable<boolean> {
    // do something to make sure authentication token works correctly
    if (this.needsAuthentication) {
      this.showModal = true;
      return Observable.create(observer => {
        this.confirm.subscribe(r => {
          this.showModal = false;
          this.needsAuthentication = !r; 
          observer.next(r);
          observer.complete();
        });
      });
    }
    else {
      return Observable.of(true);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我在这里有一个完整的实例.

http://plnkr.co/edit/C129guNJvri5hbGZGsHp?open=app%2Fapp.component.ts&p=preview


igo*_*rzg 2

使用浏览器会话:

https://developer.mozilla.org/de/docs/Web/API/Window/sessionStorage

将数据存储为 json 字符串,然后在请求失败时重新创建表单数据。