angular - http拦截器内的Angluar2路由

标签 angular typescript angular2-routing

我使用 Angular 2.4.8。与后端的通信是通过 REST。在每个请求中,我需要在 header 中发送 X-Auth-Token。 token 存储在 session 中。当 token 过期时,服务器返回 401 状态。在这种情况下,我希望应用程序转到登录页面。

我在我的项目中添加了http拦截器

@Injectable()
export class HttpInterceptor extends Http {

    constructor(backend: XHRBackend
        , defaultOptions: RequestOptions
        , private router: Router
    ) {
        super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
        return super.request(url, options).catch((error: Response) => {
            if ((error.status === 401 || error.status === 403) && 
            (window.location.href.match(/\?/g) || []).length < 2) {
                // tslint:disable-next-line:no-console
                console.log('The authentication session expires.');
                window.sessionStorage.removeItem('auth-token');
                window.location.href = window.location.href + '/login';
                // this.router.navigate(['/login']);
                return Observable.empty();
            }
            return Observable.throw(error);
        });
    }
}

而且它运作良好,除了。但我不使用路由器,而是简单的重定向和整个应用程序重新加载。当我将评论更改为

// window.location.href = window.location.href + '/login';
this.router.navigate(['/login']);

该应用程序未点击该链接。如何让路由器工作(导航)?

编辑 2018-01-22

我的app-routing.module.ts

const routes: Routes = [
    {
        path: 'login',
        component: LoginComponent,
        resolve: {
            boolean: InitResolverService
        }
    },
    {
        path: '**',
        redirectTo: 'system'
    }
];

@NgModule({
    imports: [
        RouterModule.forRoot(
            routes
            // , { enableTracing: true } // <-- debugging purposes only
        )
    ],
    exports: [
        RouterModule
    ]
})
export class AppRoutingModule { }

InitResolverService 中,我有一些逻辑要在第一次导航时执行,然后发出 true 并完成流。

LoginComponent

@Component({
    selector: 'app-login',
    templateUrl: 'login.component.html',
    styleUrls: ['login.component.less']
})
export class LoginComponent implements OnInit {
    private username: FormControl;
    private password: FormControl;
    public form: FormGroup;
    public displayDialog = false;
    isLoginButtonEnabled = true;
    isResetButtonVisible = false;

    constructor(
        private authService: AuthenticationService,
        private router: Router,
        private route: ActivatedRoute,
        private initService: InitResolverService
    ) {
        this.username = new FormControl(Validators.required);
        this.password = new FormControl(Validators.required);
        this.form = new FormGroup({
            Username: this.username,
            Password: this.password
        });
        this.form.setValue({
            Username: '',
            Password: ''
        });
        this.displayDialog = true;
    }

    ngOnInit() {
        this.initService.showSplash();
        this.authService.canActivate(this.route.snapshot, this.router.routerState.snapshot).subscribe(x => {
            if (x) {
                this.router.navigate(['/']);
            }
        });
    }
}

最佳答案

我们通过编写自己的自定义 http 服务来解决这种情况,我们通过 REST 使用所有 http 请求。

您也可以使用自定义的 http 服务;

  • 中央 api 路径
  • 使用 token 创建 header
  • 处理所有 HTTP 错误结果甚至 401

简单的代码示例

import { Injectable } from '@angular/core';
import { Http, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';

export const API_PATH = "http://apipath"

@Injectable()
export class CustomHttpService {

    constructor(
        private http: Http,
        public router: Router) { }

    headerWithToken(): Headers {
        const headers = new Headers();
        headers.set('Authorization', 'bearer ' + localStorage.getItem('TOKEN'));
        headers.set('Content-Type', 'application/json');
        return headers;
    }

    get(params: URLSearchParams, method: string): Observable<any> {
        const url = `${API_PATH}/${method}`;
        return this.http.get(url, {params: params, headers: this.headerWithToken()})
        .map(
            res => <Array<any>>res.json()
        )
        .catch(err => {
            const result = this.handleErrors(err, this);
            return result;
        });
    }

    // put same way

    // post same way

    // delete same way

    public handleErrors(error: Response, obj: any): ErrorObservable {
        const errData = error.json();
        if (error.status === 401) {
            obj.router.navigate(['/login']);
        } else if (errData.message) {
            // give a message or something
        } else {
            console.log(errData);
        }
        return Observable.throw(error.json());
    }

}

关于angular - http拦截器内的Angluar2路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42904456/

相关文章:

dependency-injection - 基本组件中的 Angular 2 DI

typescript - WebStorm & ionic 2 : ram and performance issue

对预检请求的 Angular HttpClient 响应未通过访问控制检查 : It does not have HTTP ok status

angular - 如何从 Angular 6 中的另一个模块导入服务

angular - 如何将段设置为 Angular 6 路线?

Angular Material 自定义选项卡

javascript - Angular 4 index.html不会加载任何脚本

javascript - 为什么在 JavaScript 中使用 TypeScript 类需要 `.default` ?

angular - Angular2 Router 中有抽象状态吗?

Angular2 RC.1 - 将路由器注入(inject)单元测试