上篇文章讲了vue项目使用服务器代理完成跨域,此次说一个服务端来完成这个跨域工做,就是cors跨域。javascript
其实这个自从ajax2.0就支持了。这里咱们讲下node是怎么来配置这个cors跨域的这里仍是以express框架为例,这个相对koa比较好理解点,后面会讲koa。vue
```javascript
//当你使用的是常规的跨域请求,只要设置,响应头
app.use((req, res) => {
res.header('Access-Control-Allow-Origin','*');//设置跨域须要的响应头。
})
```
复制代码
上面是对全部的请求都赞成跨域,固然,若是考虑安全,你也能够根据本身的须要,先对请求作一个验证,再决定是否加这个响应头,好比java
```javascript
app.use((req, res, next) => {
if(req.headers['origin'] && url.parse(req.headers['origin']).hostname == 'localhost'){
res.header('Access-Control-Allow-Origin','*');//自定义中间件,设置跨域须要的响应头。
}else{
next()
}
})
```
复制代码
针对普通的跨域请求只要加个响应头便可,若是是特殊的请求,好比put,delete,或者你在请求头里定义了一些本身的东西,这时你就要设置服务端相应的Access-Control-Allow-Methods和Access-Control-Allow-Headers,这个根据本身的状况来加就能够了node
是否是一会儿感受cors跨域原来这么简单。ios
在express框架里,若是要上传文件须要依赖一个中间件multer,固然也能够是别的中间件,这里以multer为例。 服务端代码面试
const express = require('express')
const router = express.Router()
const multer = require('multer') //express框架上传文件所须要的中间件
var upload = multer({ //multer中间件的使用方法能够命令行npm search multer
dest: './uploads/' //决定文件上传存放的目录
})
router.post('/upload', upload.single('avatar'), (req, res) => { //注意这里的avatar
var fileName = "";
console.log(req.file);
if (req.file != undefined) {
fileName = new Date().getTime() + "_" + req.file.originalname;
fs.rename(req.file.path, __dirname + "/" + fileName, err => {
if(err) console.log(err)
}); //重命名,加后缀,否则图片会显示乱码,打不开
}
res.send("1");
})
module.exports = router;
复制代码
客户端代码,这里要注意当你使用formData来append你的文件的时候,必定要保证文件名和服务端要接受的文件名一致。ajax
uploadImg () {
let formData = new FormData();
formData.append('avatar', this.file) //注意,这里必须上传文件的name为avatar要和服务端接收的保持一致
this.$axios.post('/api/admin/upload', formData)
复制代码
一个大点的项目会有不少请求路径,每一个路径下面还会细分,这时路由的做用就体现出来了。 在express中,它自己就带有路由模块,这里咱们来简单的演示下express
//server.js
const express = require('express')
const bodyParser = require('body-parser')
let app = express()
app.listen(8080)
app.use(bodyParser.urlencoded({
extended: false
}))
app.use('/user', require('./routers/user')) //当收到/user请求时会去找对应的user文件
app.use('/news', require('./routers/news'))
//当收到/user请求时会去找对应的news文件
//user.js,news.js也与其相似
const express = require('express')
const router = express.Router()
module.exports = router
router.get('/login', (req,res) => {})
复制代码
这样一来,咱们就把每一个请求都分离出去,让server.js看起来很清爽。npm
由于互联网上的东西彼此之间根本不认识,http就是无状态请求,只能经过相似于暗号同样的东西来肯定对方是否可信。而cookie和session就至关于这个暗号。 说下cookie和sesiion究竟是什么:axios
注意:任何放在客户端的东西都是不安全的,cookie也是,它很容易被篡改,因此通常重要信息都不会放在cookie。并且,它有大小的限制,通常只有4k。固然,为了防篡改,cookie有一个签名机制。
由于session是存储在服务端,相对会安全不少,并且理论上没有大小的限制。
使用cookie须要中间件cookie-parser,直接cnpm i cookie-parser
const cookieParser=require("cookie-parser");
app.use(cookieParser('secret'));
//注册登录post 方法;
Router.post("/login",function (req,res) {
const {userid}=req.cookies; //读取浏览器传过来的cookie
res.cookie("userid",'chyingp', {'本身设置参数'}) //设置响应头的cookie
复制代码
能够在响应头里设置: maxAge存活时间,domain域名,path路径, httpOnly是否只让服务端操做, secure是否只用在https 还有一个signed,这个就是是否签名,当为true就要签名。
res.cookie('userid', 'chyingp', {signed: true});
复制代码
这样配合上面的cookieParser就完成一个签名,下面讲下cookieParser是怎么实现这个签名的
res.cookie = (name, value, options) => {
var secret = this.req.secret;
var signed = opts.signed;
// 若是 options.signed 为true,则对cookie进行签名
if (signed) {
val = 's:' + sign(val, secret);
}
this.append('Set-Cookie', cookie.serialize(name, String(val), opts));
return this;
};
复制代码
里面的sign函数实现:
function sign (val, secret) {
return val + '.' + hmac(val, secret); //hmac是一种密钥码
}
复制代码
到这里,咱们就实现了一个简单版的cookie-parser中间件,我记得有的面试官会问能不能手写中间件,其实也没什么难的。
express用session须要cookie-session中间件 示例代码:
const cookieSession = require('cookie-session');
app.use(cookieSession({
//会话在cookie中的名称
name: 'session',
//用于签名的密钥
keys: ['j239r5ndgffhfghhgjhyyw45646fte'],
//cookie过时时间,单位毫秒
maxAge: 3600 * 1000
}));
//使用
app.get('/', function (req, res) {
//获取会话数据
console.log(req.session);
//设置会话数据
req.session.name = 'zhangsan';
res.end();
});
复制代码
到这里,其实已经可使用node进行简单的开发了,有接口,有路由,有文件上传,有cookie,session。起码用来作一个本身的我的博客是ok的。 后面,就不讲express了,在大型项目中,你们其实都更倾向于koa,由于express是基于回调的,容易死于回调。。。最新的koa是基于async await的,用起来更爽,后面我会分享一些koa的使用。