利用angular4和nodejs-express构建简单网站(十一)—HttpClient
上一节介绍了好友模块,这一节介绍和好友模块中的控件有关的三个服务程序。 用HttpClient拦截器发送用户认证信息在进入好友模块之前,需要向服务器发送认证信息,在这里使用angular的HttpClient拦截器进行发送。 import { Injectable } from '@angular/core'; import { HttpEvent,HttpInterceptor,HttpHandler,HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs/observable'; import { AuthTokenService } from './authtoken.service'; @Injectable() export class AuthInterceptor implements HttpInterceptor{ constructor( private tokenServ: AuthTokenService ){} intercept(req: HttpRequest<any>,next: HttpHandler) : Observable<HttpEvent<any>>{ //获取认证信息 const auth = this.tokenServ.getToken(); //克隆request,加入新的头信息 const authReq = req.clone({headers:req.headers.set('Authorization','Bearer ' + auth)}); return next.handle(authReq); } } 要实现拦截器,就要实现一个实现了 HttpInterceptor 接口中的 intercept() 方法的类(AuthInterceptor)。在intercept()方法中先通过AuthTokenService的getToken()方法取得认证信息。这些认证信息是在登录或注册成功后由服务器发回来的jwt认证信息。服务器如何发送这些信息请参考第三节的内容,认证信息的内容是登录或认证的用户ID。因为HttpRequest 实例的属性却是只读(readonly)的,要修改请求信息只能先克隆它。在这里利用clone()方法在请求的头部信息中加入认证信息( clone() 方法的哈希型参数允许你在复制出克隆体的同时改变该请求的某些特定属性)。最后调用 next.handle(),以便这个请求流能走到下一个拦截器,并最终传给后端处理器。 { provide: HTTP_INTERCEPTORS,useClass: AuthInterceptor,multi:true } 现在在好友模块中每个发送到服务器的请求都会在头部加上认证信息。 var expressJwt = require('express-jwt'); //使用jwt拦截 app.use(expressJwt({ secret: 'secret' })); //处置jwt异常 app.use(function (err,req,res,next) { if (err.name === 'UnauthorizedError') { res.status(401).send({ 'code': 401,'msg': 'invalid token' }); } }); app.use('/friends',friends); 一定要把处理friends访问的路由放到jwt中间件后面,不然jwt无法进行验证。 利用路由守卫保证未登录用户无法访问好友信息在上一节介绍路由时,在路由配置中加入了canActivate: [AuthGuardService],这是angular路由守卫服务,路由守卫的作用在官方文档中的解释如下: 守卫返回一个值,以控制路由器的行为: import { Injectable } from '@angular/core'; import { CanActivate,ActivatedRouteSnapshot,RouterStateSnapshot,Router } from '@angular/router'; import { UserService } from './user.service'; import { AuthTokenService } from './authtoken.service'; @Injectable() export class AuthGuardService implements CanActivate { constructor( private tokenServe: AuthTokenService,private router: Router) { } canActivate(route: ActivatedRouteSnapshot,state: RouterStateSnapshot) { if (this.tokenServe.getToken() !== null) { return true; } this.router.navigate(['/login']); return false; } } 路由守卫类也是一个注入服务类,它需要实现CanActivate接口的canActivate()方法。canActivate()方法实现了守卫代码。代码很简单,从AuthTokenService类的getToken()中获取认证信息的值,如果有就返回true,如果没有就导航到登录页面。并返回false。 birthday.service数据提供服务介绍BirthdayService类为birthday模块提供了数据服务,代码如下: import { Injectable } from '@angular/core'; import { HttpClient,HttpHeaders,HttpErrorResponse } from '@angular/common/http'; import { UserService } from '../user.service'; import 'rxjs/add/operator/map'; export class Friend { constructor( public fid: number,public fname: string,public fbirth: Date,public fnumber: string,public femail: string,public fgroup: string,public state: string,public photo: string,public uid:number ) { } } @Injectable() export class BirthdayService { constructor( private userServ: UserService,private http: HttpClient) { } //获取全部朋友信息 getFriends() { return this.http.get('http://localhost:3000/friends/friend-list',{ observe: 'response'});} //获取单个朋友信息 getFriend(id: number | string) { return this.getFriends().map(res => { if (res.body['code'] === '200') { return res.body['results'].find(result => result.fid === +id);} }); } //修改朋友信息 editFriend(friend: Friend){ const body = {'value':friend,'operate':'edit'}; return this.http.post('http://localhost:3000/friends/editfriend',body); } //新建朋友信息 newFriend(friend: Friend){ const body = {'value':friend,'operate':'new'}; return this.http.post('http://localhost:3000/friends/editfriend',body); } //删除好友 deleteFriend(friend:Friend){ const body = {'value':friend,'operate':'delete'}; return this.http.post('http://localhost:3000/friends/editfriend',body); } //错误处理 handleError(err: HttpErrorResponse): string { if (err.error instanceof Error) { return '发生错误,错误信息:' + err.error.message; } else { console.log(`Backend returned code ${err.status},body was: ${err.error['msg']}`); return err.error['msg']; } } } 首先在类外定义了一个Friend类,在这个类中定义了friend信息。BirthdayService类的主要功能有6部分:
关于birthday模块的服务程序就介绍完了。下一章将要介绍服务器端express框架如何处理这些请求。今天将我的代码传到了github上,方便大家参考。地址如下: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |