src/app/business/services/http/login.service.ts | ●●●●● patch | view | raw | blame | history | |
src/app/core/net/default.interceptor.ts | ●●●●● patch | view | raw | blame | history | |
src/app/routes/passport/login/login.component.html | ●●●●● patch | view | raw | blame | history | |
src/app/routes/passport/login/login.component.ts | ●●●●● patch | view | raw | blame | history |
src/app/business/services/http/login.service.ts
@@ -23,12 +23,14 @@ // 每2秒检查一次刷新token的时间点 setInterval( () => { if (this.needFreshFromLocal && this.isReachRefreshTime()) { if (this.canRefreshToken() && this.needFreshFromLocal && this.isReachRefreshTime()) { const _refreshToken = this._refreshToken; // 记录刷新时间 this.setRefreshTime(); // 置空needfreshtoken localStorage.setItem('needRefreshToken', 'false'); const _refreshToken = this._refreshToken; if (!!_refreshToken) { this.http.get(this.urls.refreshToken, {headers: {'X-Refrsh-Token': 'Bearer ' + _refreshToken}} ) .subscribe( @@ -84,11 +86,27 @@ const expiredTime = Number(localStorage.expiredTime); return !!this.refreshTime && !!expiredTime && this.refreshTime + (expiredTime / 2) * 60000 < new Date().getTime(); } get refreshTime(): number { private get refreshTime(): number { return Number(localStorage.refreshTime); } public clearRefreshToken() { localStorage.expiredTime = null; localStorage.refreshTime = null; localStorage.refreshToken = null; this.authorization = null; localStorage.removeItem('expiredTime'); localStorage.removeItem('refreshTime'); localStorage.removeItem('refreshToken'); } private canRefreshToken() { return !!localStorage.getItem('expiredTime') && !!localStorage.getItem('refreshTime') && !!localStorage.getItem('refreshToken'); } public refreshToken () { if (this.canRefreshToken()) { // 设置需要刷新token this.setNeedRefreshToken(); } } } src/app/core/net/default.interceptor.ts
@@ -21,26 +21,39 @@ */ @Injectable() export class DefaultInterceptor implements HttpInterceptor { private unLoginHandle: Subject<HttpErrorResponse> = new Subject<HttpErrorResponse>(); // private unLoginHandle: Subject<HttpErrorResponse> = new Subject<HttpErrorResponse>(); constructor(private injector: Injector) { this.unLoginHandle.debounceTime(800).subscribe(event => { } private isExpireModelShow = false; private unLoginHandle(event: HttpErrorResponse) { if (!!event.error) { let errorMsg = ''; const erroCode = Number.parseInt(event.error['errorCode']); const erroCode = !!event.error['errorCode'] ? Number.parseInt(event.error['errorCode']) : 0; switch (erroCode) { case 10: errorMsg = '未登录,请登录'; break; case 11: errorMsg = '登录过期,请重新登录'; break; case 12: errorMsg = '账号过期,请联系供应商'; break; case 0: errorMsg = '服务器处于离线状态'; break; default: errorMsg = '登录过期,请重新登录'; break; } if (!this.isExpireModelShow) { this.isExpireModelShow = true; // 清空refresh信息,不再刷新 this.loginService.clearRefreshToken(); this.model.info({ title: errorMsg, onOk: () => this.goTo('/passport/login') }); onOk: () => { this.isExpireModelShow = false; this.goTo('/passport/login'); } }); } } } get loginService(): LoginService { return this.injector.get<LoginService>(LoginService); } get msg(): NzMessageService { return this.injector.get(NzMessageService); } @@ -55,7 +68,8 @@ // 可能会因为 `throw` 导出无法执行 `_HttpClient` 的 `end()` 操作 // this.injector.get(_HttpClient).end(); // 业务处理:一些通用操作 switch (event.status) { const status = !!event.status ? event.status : 401; switch (status) { case 200: // 业务层级错误处理,以下假如响应体的 `status` 若不为 `0` 表示业务级异常 // 并显示 `error_message` 内容 @@ -70,8 +84,8 @@ break; case 401: // 未登录状态码 // this.goTo('/passport/login'); if (location.hash && !location.hash.endsWith('login')) { this.unLoginHandle.next(<HttpErrorResponse>event); if (!this.isLoginPage) { this.unLoginHandle(<HttpErrorResponse>event); } break; case 403: @@ -87,13 +101,11 @@ return of(event); } } private get isLoginPage(): boolean { return !!location && !!location.hash && location.hash.endsWith('login'); } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> { if (!req.headers.get('X-Refrsh-Token')) { const loginService = <LoginService>this.injector.get(LoginService); loginService.refreshToken(); } // 统一加上服务端前缀 let url = req.url; if (!url.startsWith('https://') && !url.startsWith('http://') && !url.startsWith('assets')) { @@ -107,12 +119,22 @@ return next.handle(newReq).pipe( mergeMap((event: any) => { // 允许统一对请求错误处理,这是因为一个请求若是业务上错误的情况下其HTTP请求的状态是200的情况下需要 if (event instanceof HttpResponse && event.status === 200) if (event instanceof HttpResponse && event.status === 200) { // 刷新token的请求,不设置刷新 if (!this.isLoginPage && !!newReq.headers && !newReq.headers.get('X-Refrsh-Token') && !url.startsWith('assets')) { this.loginService.refreshToken(); } return this.handleData(event); } // 若一切都正常,则后续操作 return of(event); }), catchError((err: HttpErrorResponse) => this.handleData(err)) catchError((err: HttpErrorResponse) => { return this.handleData(err); }) ); } } src/app/routes/passport/login/login.component.html
@@ -23,6 +23,7 @@ <div nz-form-explain *ngIf="(password.dirty || password.touched) && password.errors?.required">请输入密码!</div> <p nz-form-explain [ngStyle]="{'color': 'red'}" *ngIf="validateError.password_incorrect">输入用户名或者密码错误!</p> <p nz-form-explain [ngStyle]="{'color': 'red'}" *ngIf="validateError.account_expired">账号已经过期,请联系供应商!</p> <p nz-form-explain [ngStyle]="{'color': 'red'}" *ngIf="validateError.server_offline">服务器处于离线状态!</p> </div> </div> <div nz-form-item nz-row> src/app/routes/passport/login/login.component.ts
@@ -11,6 +11,7 @@ import { ReuseTabService } from '@delon/abc'; import { environment } from '@env/environment'; import { CookieService } from 'angular2-cookie/services/cookies.service'; import { debounce } from 'rxjs/operators'; @Component({ selector: 'passport-login', templateUrl: './login.component.html', @@ -87,6 +88,9 @@ this.loading = true; this.loginService.validate(this.userName.value, this.password.value).subscribe( (res: Authorization) => { this.validateError['password_incorrect'] = false; this.validateError['account_expired'] = false; this.validateError['server_offline'] = false; if (res.token != null) { // 清空路由复用信息 this.reuseTabService.clear(); @@ -109,6 +113,9 @@ } else if (errMsg.status === 401 && errMsg.errorCode === 12) { this.validateError['account_expired'] = true; this.loading = false; } else if (!errMsg.status && !errMsg.errorCode) { this.validateError['server_offline'] = true; this.loading = false; } } }