1.0 前言

现在前后端分离的开发模式是最常见的,其中就会涉及到跨域问题,这节一起学习 cors 和 csrf。

2.0 跨域资源共享(CORS)

2.0.1 基本使用

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。 —来自MDN HTTP访问控制(CORS)

如果对跨域不是很了解,强烈好好读读上面的文章。

简单讲就是,浏览器发现你的 Ajax 请求和你的当前的域名,协议,端口不一致的时候,为了安全,默认是拦截你的请求的,最常见如下:
image.png
大家把这章的demo 跑起来看看
我们在 http://localhost:3001 这个域下,发起了一个get 请求。

  1. fetch("http://localhost:3000/user/list")

不加设置的话,就会出现上面红色的信息,按照提示,我们需要设置些请求头,代码如下:

  1. app.use(async (ctx, next)=> {
  2. ctx.set('Access-Control-Allow-Origin', '*')
  3. ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild')
  4. ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS')
  5. if (ctx.method == 'OPTIONS') {
  6. ctx.body = 200
  7. } else {
  8. await next()
  9. }
  10. })

这样设置后,我们在访问下页面。
image.png
正常获取到 API 了,我们就实现了跨域访问。

2.0.2 中间件 koa2-cors

在实际工作中,我们也可以用第三方的中间件,这里讲解 koa2-cors 。

2.0.2.1 安装

  1. npm install koa2-cors --save

2.0.2.1 使用

  1. const Koa = require('koa');
  2. const cors = require('koa2-cors');
  3. const app = new Koa();
  4. app.use(cors());
  5. // 或者
  6. app.use(
  7. cors({
  8. origin: function(ctx) {
  9. return '*'; //允许所有的域名
  10. },
  11. maxAge: 5, //指定本次预检请求的有效期,单位为秒。
  12. credentials: true, //是否允许发送Cookie
  13. allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], //设置所允许的HTTP请求方法
  14. allowHeaders: ['Content-Type', 'Authorization', 'Accept'], //设置服务器支持的所有头信息字段
  15. exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] //设置获取其他自定义字段
  16. })
  17. );

3.0 CSRF

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

因为这是个安全问题,因此我们可以在每个请求都带上一个 唯一的 token 来解决这个问题,在 Koa 中我们有 koa-csrf 这个中间件来处理这个问题。

3.0.1 使用 koa-csrf

3.0.1.1 安装

  1. npm install koa-csrf

3.0.1.2 使用

先添加中间件。

  1. const Koa = require('koa');
  2. const bodyParser = require('koa-bodyparser');
  3. const session = require('koa-generic-session');
  4. const convert = require('koa-convert');
  5. const CSRF = require('koa-csrf');
  6. const app = new Koa();
  7. // 添加 CSRF 中间件
  8. app.use(new CSRF({
  9. invalidTokenMessage: 'Invalid CSRF token',
  10. invalidTokenStatusCode: 403,
  11. excludedMethods: [ 'GET', 'HEAD', 'OPTIONS' ],
  12. disableQuery: false
  13. }));
  14. // 在这里处理
  15. app.use((ctx, next) => {
  16. if (![ 'GET', 'POST' ].includes(ctx.method))
  17. return next();
  18. if (ctx.method === 'GET') {
  19. ctx.body = ctx.csrf;
  20. return;
  21. }
  22. ctx.body = 'OK';
  23. });
  24. app.listen();

在模版中带上 CSRF 。

  1. // EJS 模版
  2. <form action="/register" method="POST">
  3. <input type="hidden" name="_csrf" value="<%= csrf %>" />
  4. <input type="email" name="email" placeholder="Email" />
  5. <input type="password" name="password" placeholder="Password" />
  6. <button type="submit">Register</button>
  7. </form>

这样就实现了防 CORS 请求的问题。

4.0 总结

这节我们学习了 CORS,和 CSRF, 这 2 种工作中经常用到,大家可以好好学习下,Demo 地址