简介
Egg.js
为企业级框架和应用而生。基于Koa
开发,性能优异。
奉行『约定优于配置』
,按照一套统一的约定进行应用开发
egg中文官网上面非常详细,有koa2
基础的话,上手很快
环境搭建
环境要求:
- 要求
nodejs
版本必须大于8.0
- 建议选择
LTS
版本
-
全局安装
egg-init
:npm i egg-init -g
-
创建项目(比如叫eggdemo)
egg-init eggdemo --type=simple
cd eggdemo
npm i
- 运行项目:
npm run dev
- 使用浏览器打开
http://localhost:7001
备注:
vscode
可以安装插件eggjs
目录结构
egg-project
├── package.json
├── app.js (可选)
├── agent.js (可选)
├── app
| ├── router.js
│ ├── controller
│ | └── home.js
│ ├── service (可选)
│ | └── user.js
│ ├── middleware (可选)
│ | └── response_time.js
│ ├── schedule (可选)
│ | └── my_task.js
│ ├── public (可选)
│ | └── reset.css
│ ├── view (可选)
│ | └── home.tpl
│ └── extend (可选)
│ ├── helper.js (可选)
│ ├── request.js (可选)
│ ├── response.js (可选)
│ ├── context.js (可选)
│ ├── application.js (可选)
│ └── agent.js (可选)
├── config
| ├── plugin.js
| ├── config.default.js
│ ├── config.prod.js
| ├── config.test.js (可选)
| ├── config.local.js (可选)
| └── config.unittest.js (可选)
└── test
├── middleware
| └── response_time.test.js
└── controller
└── home.test.js
app/router.js
:用于配置URL
路由规则app/controller/**
:用于解析用户的输入,处理后返回相应的结果app/service/**
:用于编写业务逻辑层,可选,建议使用app/middleware/**
:用于编写中间件,可选app/public/**
:用于放置静态资源,可选app/extend/**
:用于框架的扩展,可选app/schedule/**
:用于定时任务,可选app/view/**
:用于放置模板文件,可选app/model/**
:用于放置领域模型,可选config/config.{env}.js
:用于编写配置文件config/plugin.js
:用于配置需要加载的插件test/**
:用于单元测试app.js
:和agent.js
用于自定义启动时的初始化工作,可选
路由-router.js
路由配置文件:app/router.js
'use strict';
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
router.get('/logout', controller.home.loginOut);
router.get('/news', controller.news.index);
router.get('/news/detail/:id', controller.news.detail);
router.get('/form1', controller.home.form1);
router.get('/form2', controller.home.form2);
router.post('/add', controller.home.add);
router.get('/shop', controller.shop.index);
};
更多路由配置参考:
控制器-controller
有下面几个属性挂在
this
上
this.ctx
: 当前请求的上下文Context
对象的实例,通过它我们可以拿到框架封装好的处理当前请求的各种便捷属性和方法。this.app
: 当前应用Application
对象的实例,通过它我们可以拿到框架提供的全局对象和方法。this.service
:应用定义的Service
,通过它我们可以访问到抽象出的业务层,等价于this.ctx.service
。this.config
:应用运行时的配置项。this.logger
:logger
对象,上面有四个方法(debug
,info
,warn
,error
),分别代表打印四个不同级别的日志
- 获取
query
参数:/news?a=123&b=kkk
'use strict';
// app/controller/news.js
const Controller = require('egg').Controller;
class NewsController extends Controller {
async index() {
const { ctx } = this;
const query = ctx.query
console.log(query) // { a: 123, b: 'kkk' }
ctx.body = 'news 页面';
}
}
module.exports = NewsController;
- 获取动态路由中的
params
参数:/news/detail/123
'use strict';
// app/controller/news.js
const Controller = require('egg').Controller;
class NewsController extends Controller {
async detail() {
const { ctx } = this;
const id = ctx.params.id
console.log(id) // 123
ctx.body = 'news detail 页面';
}
}
module.exports = NewsController;
更多控制器信息参考:
模板-view
比如使用egg-view-ejs
模板引擎
- 安装
egg-view-ejs
npm i egg-view-ejs --save
- 修改
config/plugin.js
文件
// ...
module.exports = {
// ...
ejs: {
enable: true,
package: 'egg-view-ejs'
}
}
- 修改
config/config.default.js
文件
// ...
module.exports = appInfo => {
// ...
// 配置 ejs 模板引擎
config.view = {
mapping: {
'.html': 'ejs'
}
}
// ...
}
-
在
app/
目录下新建view/
目录 -
在
app/view/
目录下新建home.html
文件(以此为示例,这个就是首页的模板文件。文件名随意,会在controller
中调用对应的文件名) -
修改
app/controller/home.js
文件
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, config, app } = this;
await ctx.render('home') // 注意这里前面有个 await
}
}
静态资源-public
-
在
app/
目录下新建public/
目录 -
静态资源放在此目录下即可(比如:有个图片
app/public/images/1.jpg
) -
在模板中使用静态资源
<img src="/public/images/1.jpg" alt="">
配置-config
比如设置接口地址
- 修改
config/config.default.js
文件(这个是默认配置文件,如果配置多环境,修改对应的config.xxx.js
文件即可)
// ...
module.exports = appInfo => {
// ...
// add your user config here
const userConfig = {
// myAppName: 'egg',
// 配置公共API
api: 'http://www.xxx.com/'
};
return {
...config,
...userConfig,
};
}
- 修改
app/controller/home.js
。在controller
中读取配置
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, config, app } = this;
console.log(config.api);
await ctx.render('home')
}
}
更多配置信息参考:
数据模型-service
Service
就是在复杂业务场景下用于做业务逻辑封装的一个抽象层
抽象的好处:
- 保持
Controller
中的逻辑更加简洁。- 保持业务逻辑的独立性,抽象出来的
Service
可以被多个Controller
重复调用。- 将逻辑和展现分离,更容易编写测试用例。
服务的命名规则
Service
文件必须放在app/service/
目录,可以支持多级目录,访问的时候可以通过目录名级联访问。app/service/biz/user.js
=>ctx.service.biz.user
(建议)****app/service/sync_user.js
=>ctx.service.syncUser
app/service/HackerNews.js
=>ctx.service.hackerNews
-
在
app/
目录下新建service/
目录 -
在
app/service/
目录下新建user.js
文件
'use strict';
const Service = require('egg').Service;
class UserService extends Service {
async getUserInfo() {
return {
name: '张三',
age: 20
}
}
}
module.exports = UserService;
- 在
app/service/
目录下新建news.js
文件
'use strict';
const Service = require('egg').Service;
class NewsService extends Service {
async getNewsList() {
const { config, service } = this
// 获取config的数据
console.log(config.api);
// 获取新闻数据
var list = ['11111','2222','333333333'];
// 调用user服务的数据
var user = await service.user.getUserInfo();
console.log(user);
return list;
}
}
module.exports = NewsService;
- 在
app/controller/
目录下添加news.js
。使用service
数据
'use strict';
const Controller = require('egg').Controller;
class NewsController extends Controller {
async index() {
const { ctx, service } = this;
var msg = 'ejs';
var list = await service.news.getNewsList();
await ctx.render('news/index',{
mag: msg,
list
});
}
}
module.exports = NewsController;
-
在
app/view/
目录下添加目录news/
-
在
app/view/news/
目录下添加模板文件index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="/public/css/basic.css">
</head>
<body>
<h2>这是一个新闻--<%=mag%></h2>
<ul>
<%for(var i=0;i<list.length;i++){%>
<li><%=list[i]%></li>
<%}%>
</ul>
<img src="/public/images/1.jpg" alt="">
</body>
</html>
更多
Service
信息参考:
HttpClient-curl
此框架基于urllib
内置实现了一个HttpClient
,应用可以非常便捷地完成任何HTTP
请求。
框架在应用初始化的时候,会自动将HttpClient
初始化到app.httpclient
。
同时增加了一个app.curl(url, options)
方法,它等价于app.httpclient.request(url, options)
。
-
修改
config/config.default.js
文件,增加配置api: 'http://www.phonegap100.com/'
-
添加
app/service/news.js
文件
'use strict';
const Service = require('egg').Service;
class NewsService extends Service {
async getNewsList() {
const { ctx, config } = this
// 通过抓取接口返回数据
// curl的方法可以获取远程的数据
var api = config.api + 'appapi.php?a=getPortalList&catid=20&page=1'
var response = await ctx.curl(api);
// console.log(response.data); // 返回的是Buffer
var data = JSON.parse(response.data); // 把Buffer类型转转换成对象
// console.log(data);
return data.result;
}
// 获取新闻详情
async getNewsContent(aid){
const { ctx, config } = this
var api = config.api + 'appapi.php?a=getPortalArticle&aid=' + aid;
var response = await ctx.curl(api);
var data = JSON.parse(response.data); //把Buffer类型转转换成对象
return data.result;
}
}
module.exports = NewsService;
- 添加
app/controller/news.js
文件
'use strict';
const Controller = require('egg').Controller;
class NewsController extends Controller {
async index() {
const { ctx, service } = this;
// 获取数据显示到新闻页面
var list = await service.news.getNewsList();
await ctx.render('news/index',{
list
})
}
async detail(){
const { ctx, service } = this
// 获取get传值
// var aid = ctx.query.aid;
var aid = ctx.params.id
var list = await service.news.getNewsContent(aid);
await ctx.render('news/detail', {
list: list[0]
})
}
}
module.exports = NewsController;
- 添加
app/view/news/index.html
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h2>新闻列表数据</h2>
<ul>
<%for(var i=0;i<list.length;i++){%>
<li>
<a href="/news/detail/<%=list[i].aid%>"><%=list[i].title%></a>
<span>---<%=list[i].dateline%></span>
</li>
<%}%>
</ul>
</body>
</html>
- 添加
app/view/news/detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="/public/css/basic.css">
</head>
<body>
<div class="content">
<h2><%=list.title%></h2>
<div>
<%-list.content%>
</div>
</div>
</body>
</html>
更多
HttpClient
信息参考:
框架扩展-extend
框架提供了多种扩展点扩展自身的功能:
Application
:对应app/extend/application.js
文件Context
:对应app/extend/context.js
文件Request
:对应app/extend/request.js
文件Response
:对应app/extend/response.js
文件Helper
:对应app/extend/helper.js
文件
在开发中,我们既可以使用已有的扩展API
来方便开发,也可以对以上对象进行自定义扩展,进一步加强框架的功能。
-
在
app/
目录下新建extend/
目录 -
在
app/extend/
目录下新建application.js
文件
/*
外部可以通过 this.app.foo()
*/
module.exports = {
foo(param) {
// this 就是 app 对象,在其中可以调用 app 上的其他方法,或访问属性
return this.config.api;
},
};
- 在
app/extend/
目录下新建context.js
文件
module.exports={
getHost(){
// this 就是 ctx 对象,在其中可以调用 ctx 上的其他方法,或访问属性
return this.request.host;
}
}
- 在
app/extend/
目录下新建request.js
文件
/*
外部可以通过 this.ctx.request.foo()
*/
module.exports = {
foo(param) {
// console.log(this);
return this.header.host;
},
};
- 在
app/extend/
目录下新建helper.js
文件
// 扩展里面引入第三方模块
/*
https://www.npmjs.com/package/silly-datetime
1.npm i silly-datetime --save
2、var sd = require('silly-datetime');
*/
var sd = require('silly-datetime');
module.exports = {
formatTime(param) {
// this 是 helper 对象,在其中可以调用其他 helper 方法
// this.ctx => context 对象
// this.app => application 对象
// console.log(new Date(param));
//格式化日期 param(时间戳)
return sd.format(new Date(param*1000), 'YYYY-MM-DD HH:mm');
},
getHelperData(){
return '我是helper里面的数据'
}
};
- 修改
app/controller/home.js
文件,使用这些自定义的扩展
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, config, app } = this;
//调用extend里面扩展的application
console.log(app.foo());
//调用extend里面扩展的ctx
console.log(ctx.getHost());
// 调用extend 扩展request的方法
console.log(ctx.request.foo());
//调用extend里面扩展的helper的方法
console.log(ctx.helper.getHelperData());
await ctx.render('home')
}
}
module.exports = HomeController;
- 修改
app/view/news/index.html
文件。使用helper
扩展formatTime
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h2>新闻列表数据</h2>
<ul>
<%for(var i=0;i<list.length;i++){%>
<li>
<a href="/news/detail/<%=list[i].aid%>"><%=list[i].title%></a>
<!-- <span>---<%=list[i].dateline%></span> -->
<span>---<%=helper.formatTime(list[i].dateline)%></span>
</li>
<%}%>
</ul>
</body>
</html>
更多框架扩展信息参考:
中间件-middleware
中间件:匹配路由前、匹配路由完成做的一系列的操作。
Egg
是基于Koa
实现的,所以Egg
的中间件形式和Koa
的中间件形式是一样的,都是基于洋葱圈模型
一般来说中间件也会有自己的配置。
在框架中,一个完整的中间件是包含了配置处理的。
我们约定一个中间件是一个放置在app/middleware
目录下的单独文件,它需要exports
一个普通的function
,接受两个参数:
options
: 中间件的配置项,框架会将app.config[${middlewareName}]
传递进来app
: 当前应用Application
的实例
-
在
app/
目录下新建middleware/
目录 -
在
app/middleware/
目录下新建printdate.js
文件(打印时间)
/*
options: 中间件的配置项,框架会将 app.config[${middlewareName}] 传递进来。
app: 当前应用 Application 的实例。
配置中间件
*/
module.exports = (options, app) => {
console.log(options);
//返回一个异步的方法
return async function printDate(ctx, next) {
console.log(new Date());
await next();
}
};
- 在
app/middleware/
目录下新建forbidip.js
文件(禁止指定的IP访问)
module.exports = (options, app) => {
//返回一个异步的方法
return async function forbidIp(ctx, next){
// 要屏蔽的ip : 1.从数据库获取 2、从参数传入
var forbidips = options.forbidips;
// 获取客户端的ip
var clientIp = ctx.request.ip;
// some 和 forEach 相似
var hasIp = forbidips.some(val => {
if (val == clientIp) {
return true;
}
})
if (hasIp) {
//屏蔽
ctx.status = 403;
ctx.body='您的ip已经被屏蔽';
} else {
await next();
}
}
};
- 修改
config/config.default.js
文件,添加配置当前项目需要使用的中间件以及中间件的参数
// ...
module.exports = appInfo => {
// ...
// add your middleware config here
config.middleware = ['printdate', 'forbidip'];
// 给printdate中间件传入的参数
config.printdate = {
aaa: 'aaaaaa'
}
config.forbidip={
forbidips:[
'127.0.0.1',
'192.168.0.10',
// '::1'
]
}
// ...
};
更多中间件信息参考:
表单
表单提交需要注意防范CSRF
攻击
方法一
- 修改
app/router.js
文件,添加路由
// ...
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
router.get('/form1', controller.home.form1);
// ...
};
- 修改
app/controller/home.js
文件
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, config, app } = this;
await ctx.render('home')
}
async form1() {
const { ctx } = this;
// this.ctx.csrf 用户访问这个页面的时候生成一个密钥
await ctx.render('form1', {
csrf: ctx.csrf
})
}
// 接收post提交的数据 this.ctx.request.body
async add() {
const { ctx } = this
console.log(ctx.request.body);
ctx.body = ctx.request.body;
}
}
module.exports = HomeController;
- 在
app/view/
目录下新建form1.html
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>表单</title>
</head>
<body>
<form action="/add?_csrf=<%=csrf%>" method="POST">
用户名: <input type="text" name="username" /> <br><br>
密 码: <input type="password" name="password" type="password" /> <br><br>
<button type="submit">提交</button>
</form>
</body>
</html>
方法二
- 修改
app/router.js
文件,添加路由
// ...
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
router.get('/form2', controller.home.form2);
// ...
};
- 修改
app/controller/home.js
文件
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, config, app } = this;
await ctx.render('home')
}
async form2() {
const { ctx } = this;
await ctx.render('form2', {
// 也可以使用 middleware/auth 中间件全局设置
csrf: ctx.csrf
})
}
// 接收post提交的数据 this.ctx.request.body
async add() {
const { ctx } = this
console.log(ctx.request.body);
ctx.body = ctx.request.body;
}
}
module.exports = HomeController;
- 在
app/view/
目录下新建form2.html
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>表单</title>
</head>
<body>
<form action="/add" method="POST">
<input type="hidden" name="_csrf" value="<%=csrf%>">
用户名: <input type="text" name="username" /> <br><br>
密 码: <input type="password" name="password" type="password" /> <br><br>
<button type="submit">提交</button>
</form>
</body>
</html>
middleware/auth
中间件全局设置方法如下:
- 在
app/middleware/
目录下新建auth.js
文件
module.exports=(option, app) => {
return async (ctx,next) => {
// 设置模板全局变量
ctx.state.csrf = ctx.csrf;
await next();
}
}
- 修改
config/config.default.js
文件
// ...
module.exports = appInfo => {
// ...
// add your middleware config here
config.middleware = ['auth'];
// ...
};
- 修改
app/controller/home.js
文件
// ...
class HomeController extends Controller {
// ...
async form2() {
const { ctx } = this;
await ctx.render('form2', {
// 这里已经使用 middleware/auth 中间件全局设置了,就不用在额外设置了
// csrf: ctx.csrf
})
}
// ...
}
// ...
更多表单相关信息参考:
Cookie
简介
cookie
是存储于访问者的计算机中的变量。可以让我们用同一个浏览器访问同一个域名的时候共享数据
HTTP
是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页面,服务器无法认识到这是同一个浏览器在访问同一个网站。每一次的访问,都是没有任何关系的
服务端可以通过响应头(set-cookie
)将少量数据响应给客户端
浏览器会遵循协议将数据保存,并在下次请求同一个服务的时候带上(浏览器也会遵循协议,只在访问符合Cookie
指定规则的网站时带上对应的Cookie
来保证安全性)
方法:
- 设置
cookie
:ctx.cookies.set(key, value, options)
- 获取
cookie
:ctx.cookies.get(key, options)
- 清除
cookie
:ctx.cookies.set(key, null)
options
参数:
{Number} maxAge
: 设置这个键值对在浏览器的最长保存时间。是一个从服务器当前时刻开始的毫秒数。{Date} expires
: 设置这个键值对的失效时间,如果设置了maxAge
,expires
将会被覆盖。如果maxAge
和expires
都没设置,Cookie
将会在浏览器的会话失效(一般是关闭浏览器时)的时候失效。{String} path
: 设置键值对生效的URL
路径,默认设置在根路径上(/
),也就是当前域名下的所有URL
都可以访问这个Cookie
。{String} domain
: 设置键值对生效的域名,默认没有配置,可以配置成只在指定域名才能访问。{Boolean} httpOnly
: 设置键值对是否可以被js
访问,默认为true
,不允许被js
访问。{Boolean} secure
: 设置键值对只在HTTPS
连接上传输,框架会帮我们判断当前是否在HTTPS
连接上自动设置secure
的值。
除了这些属性之外,框架另外扩展了3个参数的支持{Boolean} overwrite
:设置key
相同的键值对如何处理,如果设置为true
,则后设置的值会覆盖前面设置的,否则将会发送两个set-cookie
响应头。{Boolean} signed
:设置是否对Cookie
进行签名,如果设置为true
,则设置键值对的时候会同时对这个键值对的值进行签名,后面取的时候做校验,可以防止前端对这个值进行篡改。默认为true
。{Boolean} encrypt
:设置是否对Cookie
进行加密,如果设置为true
,则在发送Cookie
前会对这个键值对的值进行加密,客户端无法读取到Cookie
的明文值。默认为false
。
建议写法
设置cookie
建议的写法:
ctx.cookies.set(key, value, {
maxAge: 24 * 3600 * 1000,
httpOnly: true, // by default it's true
encrypt: true, // cookies are encrypted during network transmission
});
ctx.cookies.get('frontend-cookie', {
encrypt: true
});
设置中文Cookie
- 方法一:转码后存储,取出来后解码
console.log(new Buffer('hello, world!').toString('base64'));
// 转换成 base64 字符串:aGVsbG8sIHdvcmxkIQ==
console.log(new Buffer('aGVsbG8sIHdvcmxkIQ==', 'base64').toString());
// 还原 base64 字符串:hello, world!
- 方法二:存储时加密存,取出来的时候也加密取
ctx.cookies.set(key, value, {
maxAge: 24 * 3600 * 1000,
httpOnly: true, // by default it's true
encrypt: true, // cookies are encrypted during network transmission
});
示例
- 修改
app/controller/home.js
文件
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, config, app } = this;
/*
cookie:
1.可以实现 同一个浏览器访问同一个域的时候 不同页面之间的数据共享
2、实现数据的持久化 (关闭浏览器重新打开以后数据还存在)
参数:
第一个参数:cookies的名称
第二个参数:cookies的值
第三个参数:配置
默认情况:cookies当浏览器关闭以后就销毁了
*/
// ctx.cookies.set('username', 'zhangsan');
// 注意:默认情况下面 egg.js 里面的 cookie 没法设置中文 argument value is invalid (code: ERR_ASSERTION)
// ctx.cookies.set('username','张三');
// ctx.cookies.set('username', 'zhagnsan', {
// maxAge: 1000*3600*24, // cookie存储一天 设置过期时间后关闭浏览器重新打开cookie还存在
// httpOnly: true,
// signed: true, // 对cookie进行签名 防止用户修改cookie
// encrypt: true // 是否对cookie进行加密 如果cookie加密那么获取的时候要对cookie进行解密
// });
// 如果cookie加密以后就可以设置中文cookie (encrypt:true)
// ctx.cookies.set("userinfo", '张三', {
// maxAge: 1000*3600*24, // cookie存储一天 设置过期时间后关闭浏览器重新打开cookie还存在
// httpOnly: true,
// signed: true, // 对cookie进行签名 防止用户修改cookie
// encrypt: true // 是否对cookie进行加密 如果cookie加密那么获取的时候要对cookie进行解密
// })
ctx.cookies.set("userinfo", '张三', {
maxAge: 1000*3600*24, // cookie存储一天 设置过期时间后关闭浏览器重新打开cookie还存在
httpOnly: true,
signed: true, // 对cookie进行签名 防止用户修改cookie
encrypt: true // 是否对cookie进行加密 如果cookie加密那么获取的时候要对cookie进行解密
})
ctx.cookies.set("name", '张三', {
maxAge: 1000*3600*24, // cookie存储一天 设置过期时间后关闭浏览器重新打开cookie还存在
httpOnly: true,
signed: true, // 对cookie进行签名 防止用户修改cookie
encrypt: true // 是否对cookie进行加密 如果cookie加密那么获取的时候要对cookie进行解密
})
// cookies里面设置对象 JSON.stringify() JSON.parse()
await ctx.render('home')
}
async loginOut(){
const { ctx } = this
// 清理cookies
ctx.cookies.set('userinfo', null);
// ctx.cookies.set('userinfo', null,{
// maxAge:0
// });
ctx.redirect('/news'); /* 路由跳转 */
}
// ...
}
module.exports = HomeController;
- 修改
app/controller/news.js
文件
'use strict';
const Controller = require('egg').Controller;
class NewsController extends Controller {
async index() {
const { ctx, service } = this;
// // 获取cookie
// var username = ctx.cookies.get('username');
// console.log(username)
// // 获取加密的cookie
// var userinfo = ctx.cookies.get('userinfo', {
// encrypt:true
// });
// console.log(userinfo)
//获取cookie
var name = ctx.cookies.get('name', {
encrypt: true
});
//获取加密的cookie
var userinfo = ctx.cookies.get('userinfo', {
encrypt:true
});
console.log(name, userinfo)
// ...
await ctx.render('news/index',{
list
})
}
// ...
}
module.exports = NewsController;
更多
Cookie
信息参考:
Session
简介
cookie
数据存放在客户的浏览器上,session
数据放在服务器上。cookie
没有session
安全,别人可以分析存放在本地的cookie
并进行cookie
欺骗。session
会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用cookie
。- 单个
cookie
保存的数据不能超过4K
,很多浏览器都限制一个站点最多保存20
个cookie
session
的实现是基于cookie
的,默认配置下,用户session
的内容加密后直接存储在cookie
中的一个字段中,用户每次请求我们网站的时候都会带上这个cookie
,我们在服务端解密后使用
特别注意:
- 不要以
_
开头- 不能为
isNew
示例
- 修改
app/controller/home.js
文件
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, config, app } = this;
// 设置session
ctx.session.username = '张三';
ctx.session.userinfo = {
name: '李四',
age: 20
}
// 设置session的过期时间 修改session的默认参数 不建议用这样的方式
// ctx.session.maxAge = 5000;
await ctx.render('home')
}
// ...
}
module.exports = HomeController;
- 修改
app/controller/news.js
文件
'use strict';
const Controller = require('egg').Controller;
class NewsController extends Controller {
async index() {
const { ctx, service } = this;
var username = ctx.session.username;
var userinfo = ctx.session.userinfo;
console.log(username, userinfo)
// 设置session的过期时间 修改session的默认参数 不建议用这样的方式
// this.ctx.session.maxAge = 5000;
await ctx.render('news/index')
}
// ...
}
module.exports = NewsController;
更多
Session
信息参考:
发表评论