教程系列之二:前端全栈node的CORS跨域,文件上传,路由和cookie,session

上篇文章讲了vue项目使用服务器代理完成跨域,这次说一个服务端来完成这个跨域工作,就是cors跨域。

CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。

其实这个自从ajax2.0就支持了。这里我们讲下node是怎么来配置这个cors跨域的这里还是以express框架为例,这个相对koa比较好理解点,后面会讲koa。

```javascript
//当你使用的是常规的跨域请求,只要设置,响应头
app.use((req, res) => {
res.header('Access-Control-Allow-Origin','*');//设置跨域需要的响应头。
})
```
复制代码

上面是对所有的请求都同意跨域,当然,如果考虑安全,你也可以根据自己的需要,先对请求做一个验证,再决定是否加这个响应头,比如

```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,这个根据自己的情况来加就可以了

是不是一下子感觉cors跨域原来这么简单。

接下来我们讲下文件上传

在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;
复制代码

如果你要上传多个文件可以将上面的upload.single改为upliad.array('文件名', 数量)

客户端代码,这里要注意当你使用formData来append你的文件的时候,一定要保证文件名和服务端要接受的文件名一致。

    uploadImg () {
      let formData = new FormData();
      formData.append('avatar', this.file)   //注意,这里必须上传文件的name为avatar要和服务端接收的保持一致
      this.$axios.post('/api/admin/upload', formData)

复制代码

路由可以帮助我们极大的优化项目结构

一个大点的项目会有很多请求路径,每个路径下面还会细分,这时路由的作用就体现出来了。 在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看起来很清爽。

讲道理,cookie和session是服务端和客户端通信的重要保障。

因为互联网上的东西彼此之间根本不认识,http就是无状态请求,只能通过类似于暗号一样的东西来确定对方是否可信。而cookie和session就相当于这个暗号。 说下cookie和sesiion到底是什么:

cookie:它存储在客户端,也就是浏览器,但每次向服务端发起请求时都会带上cookie作为用户的凭证。

注意:任何放在客户端的东西都是不安全的,cookie也是,它很容易被篡改,所以一般重要信息都不会放在cookie。而且,它有大小的限制,一般只有4k。当然,为了防篡改,cookie有一个签名机制。

session:存储在服务器,不是独立存在的,一般基于cookie,就是在cookie里会保存一个id用来在服务端做验证,当然也可以用别的第三方验证

因为session是存储在服务端,相对会安全很多,而且理论上没有大小的限制。

接下来讲下怎么在express中使用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中间件,我记得有的面试官会问能不能手写中间件,其实也没什么难的。

最后说下session

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的使用。

转载于:https://juejin.im/post/5ccaff7551882540e61ff12b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值