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, //是否允许发送Cookie
allowMethods: ['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 地址。