1.0 前言
现在前后端分离的开发模式是最常见的,其中就会涉及到跨域问题,这节一起学习 cors 和 csrf。
2.0 跨域资源共享(CORS)
2.0.1 基本使用
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。 —来自MDN HTTP访问控制(CORS)
如果对跨域不是很了解,强烈好好读读上面的文章。
简单讲就是,浏览器发现你的 Ajax 请求和你的当前的域名,协议,端口不一致的时候,为了安全,默认是拦截你的请求的,最常见如下:
大家把这章的demo 跑起来看看
我们在 http://localhost:3001 这个域下,发起了一个get 请求。
fetch("http://localhost:3000/user/list")
不加设置的话,就会出现上面红色的信息,按照提示,我们需要设置些请求头,代码如下:
app.use(async (ctx, next)=> {ctx.set('Access-Control-Allow-Origin', '*')ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild')ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS')if (ctx.method == 'OPTIONS') {ctx.body = 200} else {await next()}})
这样设置后,我们在访问下页面。
正常获取到 API 了,我们就实现了跨域访问。
2.0.2 中间件 koa2-cors
在实际工作中,我们也可以用第三方的中间件,这里讲解 koa2-cors 。
2.0.2.1 安装
npm install koa2-cors --save
2.0.2.1 使用
const Koa = require('koa');const cors = require('koa2-cors');const app = new Koa();app.use(cors());// 或者app.use(cors({origin: function(ctx) {return '*'; //允许所有的域名},maxAge: 5, //指定本次预检请求的有效期,单位为秒。credentials: true, //是否允许发送CookieallowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], //设置所允许的HTTP请求方法allowHeaders: ['Content-Type', 'Authorization', 'Accept'], //设置服务器支持的所有头信息字段exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] //设置获取其他自定义字段}));
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 安装
npm install koa-csrf
3.0.1.2 使用
先添加中间件。
const Koa = require('koa');const bodyParser = require('koa-bodyparser');const session = require('koa-generic-session');const convert = require('koa-convert');const CSRF = require('koa-csrf');const app = new Koa();// 添加 CSRF 中间件app.use(new CSRF({invalidTokenMessage: 'Invalid CSRF token',invalidTokenStatusCode: 403,excludedMethods: [ 'GET', 'HEAD', 'OPTIONS' ],disableQuery: false}));// 在这里处理app.use((ctx, next) => {if (![ 'GET', 'POST' ].includes(ctx.method))return next();if (ctx.method === 'GET') {ctx.body = ctx.csrf;return;}ctx.body = 'OK';});app.listen();
在模版中带上 CSRF 。
// EJS 模版<form action="/register" method="POST"><input type="hidden" name="_csrf" value="<%= csrf %>" /><input type="email" name="email" placeholder="Email" /><input type="password" name="password" placeholder="Password" /><button type="submit">Register</button></form>
这样就实现了防 CORS 请求的问题。
4.0 总结
这节我们学习了 CORS,和 CSRF, 这 2 种工作中经常用到,大家可以好好学习下,Demo 地址。
