From 6232645481874ed9cefcfb2c2137816b156b95d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BD=B6=E5=93=A5?= Date: Sun, 16 Jul 2017 22:56:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BE=9D=E8=B5=96=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + README.md | 18 +++++++---- package.json | 39 +++++++++++++----------- publicKey.pub | 1 + src/app.js | 37 +++++++++++----------- src/controllers/auth.js | 49 ++++++++++++++++++++++++++++++ src/middleware/ErrorRoutesCatch.js | 20 ++++++++++++ src/routes/main-routes.js | 5 +-- 8 files changed, 127 insertions(+), 43 deletions(-) create mode 100644 publicKey.pub create mode 100644 src/controllers/auth.js create mode 100644 src/middleware/ErrorRoutesCatch.js diff --git a/.gitignore b/.gitignore index faf3925..4f3f40d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ test/unit/coverage test/e2e/reports selenium-debug.log .idea/ +package-lock.json diff --git a/README.md b/README.md index 29d545d..29b12c1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Koa2 RESTful API 服务器脚手架 这是一个基于Koa2的轻量级RESTful API Server脚手架,支持ES6。 -**注意:因升级Koa版本至2.2.0,为配合相应的依赖项,故需要Node.js版本大于等于v7.8.0,NPM大于等于v4.2.0。** +**注意:因升级Koa版本至2.3.0,为配合相应的依赖项,故需要Node.js版本大于等于v8.0.0,NPM大于等于v5.0.0。** 约定使用JSON格式传输数据,POST、PUT、DELET方法支持的Content-Type为`application/x-www-form-urlencoded、multipart/form-data、application/json`可配置支持跨域。非上传文件推荐application/x-www-form-urlencoded。通常情况下返回application/json格式的JSON数据。 @@ -153,7 +153,7 @@ $ docker run -itd -p 80:80 -p 443:443 -v `pwd`/nginx_config:/etc/nginx/conf.d ng > 引入插件的版本将会持续更新 引入的插件: -`koa@2 koa-body@2 koa-router@next koa-session2 koa-static2 koa-compose require-directory babel-cli babel-register babel-plugin-transform-runtime babel-preset-es2015 babel-preset-stage-2 gulp gulp-eslint eslint eslint-config-standard eslint-friendly-formatter eslint-plugin-html eslint-plugin-promise nodemailer promise-mysql` +`koa@2 koa-body@2 koa-router@next koa-static2 koa-compose require-directory babel-cli babel-register babel-plugin-transform-runtime babel-preset-es2015 babel-preset-stage-2 gulp gulp-eslint eslint eslint-config-standard eslint-friendly-formatter eslint-plugin-html eslint-plugin-promise nodemailer promise-mysql 等` **koa2**: HTTP框架  Synopsis: HTTP framework. @@ -167,10 +167,6 @@ $ docker run -itd -p 80:80 -p 443:443 -v `pwd`/nginx_config:/etc/nginx/conf.d ng  Synopsis: Router middleware for koa.  From: https://github.com/alexmingoia/koa-router/tree/master/ -**koa-session2**: Session中间件 - Synopsis: Middleware for Koa2 to get/set session. - From: https://github.com/Secbone/koa-session2 - **koa-static2**: 静态资源中间件  Synopsis: Middleware for Koa2 to serve a folder under a name declared by user.  From: https://github.com/Secbone/koa-static2 @@ -248,6 +244,10 @@ $ docker run -itd -p 80:80 -p 443:443 -v `pwd`/nginx_config:/etc/nginx/conf.d ng **其它经常配合Koa2的插件:** +**koa-session2**: Session中间件 + Synopsis: Middleware for Koa2 to get/set session. + From: https://github.com/Secbone/koa-session2 + **koa-nunjucks-2**: 一个好用的模版引擎,可用于前后端,nunjucks:https://github.com/mozilla/nunjucks @@ -476,6 +476,12 @@ request.post('/api').form({key:'value'}), function(err,httpResponse,body){ /* .. 更新说明 -------- +*v0.2 2017年07月16日22:48:34* + +1. 升级koa为2.3.0版本。 +2. 将koa-session2替换为koa-jwt,添加了jsonwebtoken。 +3. 升级了以下依赖的版本: koa@2.3.0, koa-body@2.3.0, koa-router@7.2.1, babel-cli@6.24.1, babel-preset-es2015@6.24.1, babel-preset-stage-2@6.24.1, babel-register@6.24.1, eslint-plugin-promise@3.5.0, koa-compose@4.0.0, koa-session2@2.2.4, nodemailer@4.0.1, sequelize@4.3.2, eslint@4.2.0, eslint-config-standard@10.2.1, eslint-friendly-formatter@3.0.0, eslint-plugin-html@3.1.0, gulp-eslint@4.0.0, koa-logger@3.0.1 + *v0.1 2017年04月07日11:46:02* 1. 升级koa为2.2.0版本。 diff --git a/package.json b/package.json index 0f0f83d..3c08b95 100644 --- a/package.json +++ b/package.json @@ -10,34 +10,37 @@ "production": "node dist/app.js" }, "dependencies": { - "koa": "^2.2.0", - "koa-body": "^2.0.0", - "koa-compose": "^3.2.1", - "koa-router": "^7.1.1", - "koa-session2": "^1.0.8", + "jsonwebtoken": "^7.4.1", + "koa": "^2.3.0", + "koa-body": "^2.3.0", + "koa-compose": "^4.0.0", + "koa-jwt": "^3.2.2", + "koa-router": "^7.2.1", "koa-static2": "^0.1.8", "mysql": "^2.12.0", - "nodemailer": "^2.7.2", + "nodemailer": "^4.0.1", "promise-mysql": "^3.0.1", "require-directory": "^2.1.1", - "sequelize": "^3.30.4" + "sequelize": "^4.3.2" }, "devDependencies": { - "babel-cli": "^6.22.2", + "babel-cli": "^6.24.1", "babel-plugin-transform-runtime": "^6.22.0", - "babel-preset-es2015": "^6.22.0", - "babel-preset-stage-2": "^6.22.0", - "babel-register": "^6.22.0", - "eslint": "^3.19.0", - "eslint-config-standard": "^6.2.1", - "eslint-friendly-formatter": "^2.0.7", - "eslint-plugin-html": "^1.7.0", - "eslint-plugin-promise": "^3.4.0", + "babel-preset-es2015": "^6.24.1", + "babel-preset-stage-2": "^6.24.1", + "babel-register": "^6.24.1", + "eslint": "^4.2.0", + "eslint-config-standard": "^10.2.1", + "eslint-friendly-formatter": "^3.0.0", + "eslint-plugin-html": "^3.1.0", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-node": "^5.1.0", + "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", "gulp": "^3.9.1", - "gulp-eslint": "^3.0.1", + "gulp-eslint": "^4.0.0", "gulp-nodemon": "^2.2.1", - "koa-logger": "^1.3.1" + "koa-logger": "^3.0.1" }, "engines": { "node": ">= 7.8.0", diff --git a/publicKey.pub b/publicKey.pub new file mode 100644 index 0000000..b19facd --- /dev/null +++ b/publicKey.pub @@ -0,0 +1 @@ +wqdjkwl1e21FQlk1j2 diff --git a/src/app.js b/src/app.js index 13096ea..5fe5354 100644 --- a/src/app.js +++ b/src/app.js @@ -1,34 +1,23 @@ import Koa2 from 'koa' import KoaBody from 'koa-body' -import KoaSession from 'koa-session2' import KoaStatic from 'koa-static2' import { System as SystemConfig } from './config' import path from 'path' import MainRoutes from './routes/main-routes' +import ErrorRoutesCatch from './middleware/ErrorRoutesCatch' import ErrorRoutes from './routes/error-routes' -import PluginLoader from './lib/PluginLoader' +import jwt from 'koa-jwt' +import fs from 'fs' +// import PluginLoader from './lib/PluginLoader' const app = new Koa2() const env = process.env.NODE_ENV || 'development' // Current mode +const publicKey = fs.readFileSync(path.join(__dirname, '../publicKey.pub')) + app - .use(KoaBody({ - multipart: true, - strict: false, - jsonLimit: '20mb', - formLimit: '10mb', - textLimit: '20mb', - formidable: { - uploadDir: path.join(__dirname, '../assets/uploads') - } - })) // Processing request - .use(KoaStatic('assets', path.resolve(__dirname, '../assets'))) // Static resource - .use(KoaSession({ - key: SystemConfig.Session_Key - })) // Set Session - .use(PluginLoader(SystemConfig.System_plugin_path)) .use((ctx, next) => { if (ctx.request.header.host.split(':')[0] === 'localhost' || ctx.request.header.host.split(':')[0] === '127.0.0.1') { ctx.set('Access-Control-Allow-Origin', '*') @@ -40,6 +29,20 @@ app ctx.set('Access-Control-Allow-Credentials', true) // 允许带上 cookie return next() }) + .use(ErrorRoutesCatch()) + .use(KoaStatic('assets', path.resolve(__dirname, '../assets'))) // Static resource + .use(jwt({ secret: publicKey }).unless({ path: [/^\/public|\/user\/login|\/assets/] })) + .use(KoaBody({ + multipart: true, + strict: false, + formidable: { + uploadDir: path.join(__dirname, '../assets/uploads/tmp') + }, + jsonLimit: '10mb', + formLimit: '10mb', + textLimit: '10mb' + })) // Processing request + // .use(PluginLoader(SystemConfig.System_plugin_path)) .use(MainRoutes.routes()) .use(MainRoutes.allowedMethods()) .use(ErrorRoutes()) diff --git a/src/controllers/auth.js b/src/controllers/auth.js new file mode 100644 index 0000000..cb70ff0 --- /dev/null +++ b/src/controllers/auth.js @@ -0,0 +1,49 @@ +import jwt from 'jsonwebtoken' +import fs from 'fs' +import path from 'path' + +const publicKey = fs.readFileSync(path.join(__dirname, '../../publicKey.pub')) + +// 用户登录的时候返回token +// let token = jwt.sign({ +// userInfo: userInfo // 你要保存到token的数据 +// }, publicKey, { expiresIn: '7d' }) + +/** + * 检查授权是否合法 + */ +export let CheckAuth = (ctx) => { + let token = ctx.request.header.authorization + try { + let decoded = jwt.verify(token.substr(7), publicKey) + if (decoded.userInfo) { + return { + status: 1, + result: decoded.userInfo + } + } else { + return { + status: 403, + result: { + errInfo: '没有授权' + } + } + } + } catch (err) { + return { + status: 503, + result: { + errInfo: '解密错误' + } + } + } +} + +export let Post = (ctx) => { + switch (ctx.params.action) { + case 'check': + return CheckAuth(ctx).then(result => { ctx.body = result }) + default: + return CheckAuth(ctx).then(result => { ctx.body = result }) + } +} diff --git a/src/middleware/ErrorRoutesCatch.js b/src/middleware/ErrorRoutesCatch.js new file mode 100644 index 0000000..8e32f34 --- /dev/null +++ b/src/middleware/ErrorRoutesCatch.js @@ -0,0 +1,20 @@ +module.exports = function () { + return function (ctx, next) { + return next().catch((err) => { + switch (err.status) { + case 401: + ctx.status = 200 + ctx.body = { + status: 401, + result: { + err: 'Authentication Error', + errInfo: 'Protected resource, use Authorization header to get access.' + } + } + break + default: + throw err + } + }) + } +} diff --git a/src/routes/main-routes.js b/src/routes/main-routes.js index f4c60eb..d67648d 100644 --- a/src/routes/main-routes.js +++ b/src/routes/main-routes.js @@ -4,13 +4,14 @@ import controllers from '../controllers/index.js' const router = new KoaRouter() router - .get('/', function (ctx, next) { + .get('/public/get', function (ctx, next) { ctx.body = '禁止访问!' - }) // HOME 路由 + }) // 以/public开头则不用经过权限认证 .all('/upload', controllers.upload.default) .get('/api/:name', controllers.api.Get) .post('/api/:name', controllers.api.Post) .put('/api/:name', controllers.api.Put) .del('/api/:name', controllers.api.Delect) + .post('/auth/:action', controllers.auth.Post) module.exports = router