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

上篇文章講了vue項目使用服務器代理完成跨域,此次說一個服務端來完成這個跨域工做,就是cors跨域。javascript

CORS背後的基本思想是使用自定義的HTTP頭部容許瀏覽器和服務器相互瞭解對方,從而決定請求或響應成功與否。

其實這個自從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;
複製代碼

若是你要上傳多個文件能夠將上面的upload.single改成upliad.array('文件名', 數量)

客戶端代碼,這裏要注意當你使用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

講道理,cookie和session是服務端和客戶端通訊的重要保障。

由於互聯網上的東西彼此之間根本不認識,http就是無狀態請求,只能經過相似於暗號同樣的東西來肯定對方是否可信。而cookie和session就至關於這個暗號。 說下cookie和sesiion究竟是什麼:axios

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

相關文章
相關標籤/搜索