天天看點

Egg.js中使用extend、Cookie、Session的基本方式

一、初始化

  1. 項目初始化
egg-init spider --type=simple
複制代碼      
  1. 安裝依賴
npm i
複制代碼      
  1. 運作測試項目
npm run dev
複制代碼      
  1. 配置模闆引擎
npm i egg-view-ejs 
複制代碼      
  1. 找到app/config/plugin.js
exports.ejs = {
    enable: true,
    package: 'egg-view-ejs'
};
複制代碼      
  1. 找到app/config/config.default.js
config.view = {
    mapping: {
        '.html': 'ejs'
    }
}
複制代碼      
  1. 配置公共的URL位址(config/config.default.js)
config.api = "http://www.phonegap100.com/"
複制代碼      

二、抓取新聞接口實作新聞清單與詳情

  1. 定義新聞清單和新聞詳情路由
router.get('/news', controller.news.index);
router.get('/newscontent', controller.news.content);
複制代碼      
  1. 在service中擷取新聞清單的資料和新聞詳情的資料
async index() {
    let list = await this.service.news.getNewsList();
    await this.ctx.render('news',{
      list
    })
  }
async content() {
    const aid = this.ctx.query.aid;
    console.log(aid);
    const detail = await this.service.news.getNewsContent(aid);
    await this.ctx.render('newscontent',{
      detail:detail[0]
    })
  }
複制代碼      
記住:渲染的時候,一定要使用await,因為這是異步渲染,不然可能會報404錯誤。
  1. 在view視圖層中定義模闆引擎
<h2>新聞清單</h2>
  <ul>
    <%for (let i = 0; i < list.length; i++) {%>
      <li><a href="/newscontent?aid=<%=list[i].aid%>"><%=list[i].title%></a></li>
    <%}%>
  </ul>
複制代碼      

三、Egg.js架構拓展extend

通過Application

  1. 在app檔案夾下建立檔案夾extend
  2. 在extend檔案夾下面建立一個application.js,在這個檔案中暴露的函數,均可以通過this.app.xxx來進行調用,但是在application.js内部this就是app。
module.exports = {
  foo(param) {
    // this 就是 app 對象,在其中可以調用 app 上的其他方法,或通路屬性
    console.log(this);
  },
};
複制代碼      

通過Context

  1. 在extend檔案夾下建立context.js
  2. 在context.js中定義想要拓展的函數
module.exports = {
  getHost(param) {
    // this 就是 ctx 對象,在其中可以調用 ctx 上的其他方法,或通路屬性
    return this.request.header.host; 
  },
};
複制代碼      
  1. 調用拓展的函數
console.log(this.ctx.getHost());
複制代碼      
更多其他的拓展方式請通路官網: Egg拓展

通過拓展的形式将時間戳轉換為時間字元串

  1. 安裝相關子產品并引入
const sd = require('silly-datetime')
module.exports = {
  formatTime (param) {
    // this 是 helper 對象,在其中可以調用其他 helper 方法
    // this.ctx => context 對象
    // this.app => application 對象
    return sd.format(new Date(param*1000),'YYYY-MM-DD HH:mm')
  },
};
複制代碼      
  1. 在模闆引擎中使用
<%=helper.formatTime(list[i].dateline)%>
複制代碼      
  1. 在控制器中使用
通過this.ctx.helper.xxx()
console.log(this.ctx.helper.sendHello());
複制代碼      

通過Request

  1. 在extend檔案夾下面建立request.js
module.exports = {
  foo() {
    return this.header.host
  },
};
複制代碼      
  1. 在控制器中調用
console.log(this.ctx.request.foo());
複制代碼      

四、禁止指定IP的通路

Egg調用中間件的時機

比對路由前或比對路由完成時。

中間件的定義與配置、傳值

  1. 在app檔案夾下建立一個檔案夾middleware檔案夾,并在下面建立一個printdate.js
module.exports = (options,app) => {
  console.log(options);
  // 傳回一個異步的方法
  return async function printDate(ctx,next) {
    console.log(new Date());
    await next();
  }
}
複制代碼      
  1. 在config/config.default.js
config.middleware = ['printdate'];
  config.printdate = {
    aaa: '123'
  }
複制代碼      

禁止指定ip通路

  1. 在app/middleware中建立一個forbidip.js
module.exports = (options,app) => {
  // 傳回一個異步的方法
  return async function printDate(ctx,next) {
    // 要屏蔽的IP
    const forbidIp = "127.0.0.1";
    // 擷取用戶端的ip
    if (ctx.request.ip === forbidIp) {
      ctx.status = 403;
      ctx.body = "您的IP已經被屏蔽"
    } else {
      await next();
    }
  }
}
複制代碼      
  1. 在config/config.default.js中注冊這個中間件
config.middleware = ['printdate','forbidip'];
複制代碼      

五、POST送出資料并通過中間件配置CSRF

  1. 模闆引擎中定義好csrf
<form action="/add?_csrf=<%=csrf%>" method="post">
    使用者名:<input type="text" name="username"><br><br>
    密碼:<input type="password" name="password"><br><br>
    <button type="submit">送出</button>
  </form>
複制代碼      
  1. 在app/middleware下建立一個auth.js
module.exports = (option,app) => {
  return async function auth(ctx,next) {
    
    // 設定模闆全局變量,之是以要這樣做,是為了讓模闆引擎能夠直接擷取到csrf,而不用每次都傳遞csrf
    ctx.state.csrf = ctx.csrf;
    await next();
  }
}
複制代碼      

六、Egg.js中使用Cookie

  1. 設定cookie的方法
this.ctx.cookies.set('name','zhangsan');
複制代碼      
  1. 擷取cookie的方法
this.ctx.cookies.get('name');
複制代碼      
下面介紹下,如何在一個控制器中設定cookie,在另一個控制器中擷取cookie
  • 設定cookie的控制器
async index() {
    const { ctx } = this;
    // 設定cookie
    const username = this.ctx.cookies.set('username','zhangsan');
    // this.ctx.csrf : 使用者通路這個頁面的時候,生成一個密鑰
    await ctx.render('home')
  }
複制代碼      
  • 擷取cookie的控制器
async index() {
    const username = this.ctx.cookies.get('username')
    await this.ctx.render('news', {
      username
    })
  }
複制代碼      
  1. 設定cookie的緩存有效時長
const username = this.ctx.cookies.set('username','zhangsan',{
      maxAge: 1000*3600*24
    });
複制代碼      
  1. 設定參數
const username = this.ctx.cookies.set('username','zhangsan',{
  maxAge: 1000*3600*24,
  httpOnly: true,
  signed: true,     //對cookie進行簽名,防止使用者修改cookie
  encrypt: true,         // 如果對cookie進行加密,擷取的時候需要解密
});
複制代碼      
  1. 清除cookie
this.ctx.cookies.set('username',null)
複制代碼      

Egg.js中使用Seesion

cookie是儲存在用戶端的浏覽器上,而Session則是儲存在伺服器上。當浏覽器通路伺服器并發送第一次請求的時候,服務端會建立一個session對象,生成一個類似與key,value的鍵值對,然後将key(cookie)傳回到浏覽器,浏覽器下次再通路的時候,攜帶key(cookie),找到對應的session(value)。浏覽器首次通路目标伺服器的時候,目标伺服器的響應頭中會包含一個set-cookie字段,浏覽器第二次通路将攜帶cookie進行通路。
  1. 在控制器中設定session
async setSession() {
    this.ctx.session.username = "餘波";
  }
複制代碼      
  1. 在控制器中擷取session
async index() {
    // 拿到session,并渲染到news頁面中
    const username = this.ctx.session.username;
    await this.ctx.render('news', {
      username
    })
  }
複制代碼      
  1. 設定session的過期時間(也可以在config中配置session)
this.ctx.session.maxAge = 5000;
複制代碼      
  1. 在config.default.js中配置session
config.session = {
    maxAge: 1000*5
}