最终目的是实现一套基于jwt的单点登录系统,可以用于日常外包项目.整体逻辑技术准备egg.js前置知识1.eggjs是基于koa2的,可以认为是koa2框架层面的约束。它需要一个koa2基础。可以参考koa2文档。2.对于koa2洋葱圈模型的分析,可以看这里3.node8.x版本,可以方便的使用async/await来写异步代码4.egg.js官方文档目录结构和框架协议介绍的地方会用到,其他功能以后慢慢摸索├──package.json├──app|├──router.js│├──控制器│|└──user.js│├──服务│|└──user.js│├──中间件│|└──checkToken.js│└──模型│└──user.js├──配置|├──plugin.js|├──配置。上面的default.js是框架约定好的目录。由于我们的前端是分离的,所以不再需要view目录:app/router.js用于配置URL路由规则。app/controller/**用于解析用户输入,处理后返回相应的结果。app/service/**用于编写业务逻辑层。app/middleware/**用于编写中间件。config/config.{env}.js用于编写配置文件。config/plugin.js用于配置需要加载的插件。tips修改cors修改plugin.jsexports.cors={enable:true,package:'egg-cors',}修改config.default.jsexports.security={csrf:{enable:false,ignoreJSON:true},domainWhiteList:['*']}exports.cors={origin:'*',allowMethods:'GET,HEAD,PUT,POST,DELETE,PATCH'}在egg.js中使用redis安装,请看mac下安装redis,其他操作系统请自行百度。Redis是什么请参考egg-redis文档。yarn添加egg-redis修改plugin.jsexports.redis={enable:true,package:'egg-redis',}modifyconfig.default.jsexports.redis={client:{port:[port],host:'127.0.0.1',password:[password],db:0}}注意一定要改默认端口!必须更改默认端口!必须更改默认端口!请看:RedisUnauthorizedAccess缺陷容易导致系统被黑,请修改redis.conf:requirepass(密码),port(端口)可能会遇到redis快照关闭无法写入数据的情况,还有一个会报错,类似:MISCONFRedis配置为保存RDB快照,但目前无法持久化到磁盘上。可能修改数据集的命令被禁用,因为此实例配置为在RDB快照失败时在写入期间报告错误(stop-writes-on-bgsave-error选项)。有关RDB错误的详细信息,请检查Redis日志。解决方法是修改redis.conf:stop-writes-on-bgsave-error为no。在egg.js中使用postgresql安装。请看mac下postgresql的安装。其他操作系统请自行百度。使用方法请参考egg-sequelize文档。与MySQL相比,PostgreSQL有哪些优势?yarnaddegg-sequelizeyarnaddpgpg-hstoremodifyplugin.jsexports.sequelize={enable:true,package:'egg-sequelize'}modifyconfig.default.jsexports.sequelize={方言:'postgres',数据库:'postgres',主机:'localhost',端口:'8888',用户名:'postgres',密码:'123456'}生成令牌yarnaddjsonwebtokenvarjwt=require('jsonwebtoken');vartokenKey='tokenkey'vartoken=jwt.sign({foo:'bar'},tokenKey);vardecoded=jwt.verify(token,tokenKey);console.log(decoded.foo)//bar后端业务逻辑前端业务逻辑中间件蛋。js基于Koa2,可以方便的引入到Koa中间件生态中。在我们的应用中,并不是所有的请求都需要验证token,所以可以通过中间件来处理。接下来,我们将编写一个中间件。写法app/model/checkToken.jsconst{verify}=require('jsonwebtoken')constmoment=require('moment')module.exports=options=>{returnasyncfunctioncheckToken(ctx,next){const{jwtKey}=ctx.app.config.appConfigconst{request:{path,header:{token}}}=ctxconst{exclude=[]}=optionsletdecodedJwt={}try{if(exclude.indexOf(path.replace('/',''))===-1){//需要token的接口decodedJwt=verify(token,jwtKey)//tokenexp超时if(moment().isAfter(decodedJwt.exp)){throw{code:-340,msg:'token过期'}}}else{//不需要token的接口decodedJwt.exp=-1}}catch(error){ctx.app.logger.error('tokenerror',error)if(error.code){ctx.body=error}else{ctx.body={code:-360,msg:'tokenerror'}}}if(decodedJwt.exp){awaitnext()}}}配置修改config.default.jsexports.middleware=['checkToken']//中间件会按顺序执行//中间件需要的配置项可以通过app.config[${middlewareName}]exports.checkToken={exclude:['login','signup']}
