【Angular实战/网易云】用户签到(interceptor使用)

一. 用户签到的难点

为什么这么简单的东西也要单独拿出来讲一讲?主要还是跨域的问题。

如果不考虑跨域的话,只要给click绑定以下事件就行了:

  onSignin() {
    this.memberSerice.signIn().subscribe(
      res => console.log(res),
      error => console.log(error)
    );
  }

但是大家都知道,http是无状态的,如果人家没给你一个标识符,人家就无法认出你。这就有了cookie,他会主动向你发一个cookie,然后你携带这这个cookie去访问服务器,诶,他就能认出你来了。

然而我们本次项目开启的服务是http://localhost:3000, 而angular项目跑在http://localhost:4200。这就会引发跨域问题,默认情况下你是无法携带cookie访问我们的服务的。 

当然,我们也能在不修改以上代码的情况下,通过添加http-interceptor来发送跨域的cookie。

 

二. 从同源策略讲起

什么才能叫作同源?一定要同时满足以下三点:

  • 策略相同:不能是https和http
  • 域名相同:不能是baidu.com和google.com
  • 端口相同:不能是80到8080

如果有一个条件不满足,那就发生了跨域现象。

 

三. CORS

CORS就是跨域资源共享。按理来讲,如果要跨域访问资源,就会有很多限制,比如无法访问localStorage, 无法收到ajax的response等等。但是只要正确设置了CORS头,就能跨域访问资源了。

以最简单的GET请求为例(之所以称它为简单,是因为他无法触发浏览器的preflight请求),如果服务器的response设置了Access-Control-Allow-Origin: *。那么客户端就能跨域访问资源了。

 

四. 浏览器的preflight请求

对于一些复杂的请求(比如有一些side effect的请求),会触发浏览器的preflight请求。

说得这么绕,到底是咋回事呢?简单点就是说,浏览器先发一个request帮你问问服务器能不能跨域,得到“能”的答复后就让你发送,否则就阻止你的发送

什么才叫复杂的请求呢?请见:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

五. 携带跨域cookie访问服务器

 cookie这个东西和localStoarge不一样,你还是能够设置CORS请求头来访问服务器的。这里我们可以通过设置withCredentials为true来允许跨域。

同时,服务端也要设置好各种响应头才能让我们的浏览器相应跨域行为:

// CORS & Preflight request
app.use((req, res, next) => {
  if(req.path !== '/' && !req.path.includes('.')){
    res.set({
      'Access-Control-Allow-Credentials': true,
      // 对于携带cookie的请求来说,origin是不能为*的
      'Access-Control-Allow-Origin': req.headers.origin || '*',
      'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
      'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
      'Content-Type': 'application/json; charset=utf-8'
    })
  }
  req.method === 'OPTIONS' ? res.status(204).end() : next()
})

 

六. http-intercetor

在angular中我们可以通过http-interceptor来拦截我们的http请求,如果要给请求添加withCredential属性,可以这么做:

@Injectable()
export class CommonInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 允许跨域的cookie
    return next.handle(req.clone({
      withCredentials: true
    })).pipe(catchError(this.handleError));
  }
}

然后我们创建一个index.ts导出一下:

export const httpInterceptorProvides = [
  { provide: HTTP_INTERCEPTORS, useClass: CommonInterceptor, multi: true }
];

就可以带着cookie访问服务器了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值