From 859056a7613b359eedd2348d4426133ca25c73d8 Mon Sep 17 00:00:00 2001 From: tumobi Date: Tue, 25 Jul 2017 22:52:21 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E6=B7=BB=E5=8A=A0=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=92=8Ctoken=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/api/controller/address.js | 12 +++--- src/api/controller/auth.js | 43 +++++++++++-------- src/api/controller/base.js | 21 +++++++++- src/api/controller/cart.js | 8 ++-- src/api/controller/collect.js | 13 ++++-- src/api/controller/goods.js | 4 +- src/api/controller/order.js | 8 ++-- src/api/controller/search.js | 4 +- src/api/service/token.js | 75 ++++++++++++++++++++++++++++++++++ src/common/bootstrap/global.js | 2 +- src/common/config/config.js | 10 ++--- src/common/config/session.js | 2 +- src/common/model/cart.js | 6 +-- 14 files changed, 161 insertions(+), 48 deletions(-) create mode 100644 src/api/service/token.js diff --git a/package.json b/package.json index a03587e..dbada62 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "babel-runtime": "6.x.x", "cheerio": "^0.22.0", "gm": "^1.23.0", + "jsonwebtoken": "^7.4.1", "lodash": "^4.17.4", "moment": "^2.18.1", "redis": "^2.3.0", diff --git a/src/api/controller/address.js b/src/api/controller/address.js index 73bd3d1..eaec7b1 100644 --- a/src/api/controller/address.js +++ b/src/api/controller/address.js @@ -8,7 +8,7 @@ export default class extends Base { * @return {Promise} [] */ async listAction(){ - let addressList = await this.model('address').where({user_id: 1}).select(); + let addressList = await this.model('address').where({user_id: think.userId}).select(); let itemKey = 0; for ( let addressItem of addressList) { addressList[itemKey].province_name = await this.model('region').getRegionName(addressItem.province_id); @@ -29,7 +29,7 @@ export default class extends Base { */ async detailAction(){ let addressId = this.get('id'); - let addressInfo = await this.model('address').where({user_id: 1, id: addressId}).find(); + let addressInfo = await this.model('address').where({user_id: think.userId, id: addressId}).find(); if ( !think.isEmpty(addressInfo)) { addressInfo.province_name = await this.model('region').getRegionName(addressInfo.province_id); addressInfo.city_name = await this.model('region').getRegionName(addressInfo.city_id); @@ -55,19 +55,19 @@ export default class extends Base { city_id: this.post('city_id'), district_id: this.post('district_id'), address: this.post('address'), - user_id: 1, + user_id: getLoginUserId(), is_default: this.post('is_default') == true ? 1 : 0 }; if (think.isEmpty(addressId)) { addressId = await this.model('address').add(addressData); } else { - await this.model('address').where({id: addressId, user_id: 1}).update(addressData); + await this.model('address').where({id: addressId, user_id: think.userId}).update(addressData); } //如果设置为默认,则取消其它的默认 if (this.post('is_default') == true) { - await this.model('address').where({id: ['<>', addressId], user_id: 1}).update({ + await this.model('address').where({id: ['<>', addressId], user_id: think.userId}).update({ is_default: 0 }); } @@ -84,7 +84,7 @@ export default class extends Base { async deleteAction(){ let addressId = this.post('id'); - await this.model('address').where({id: addressId, user_id: 1}).delete(); + await this.model('address').where({id: addressId, user_id: think.userId}).delete(); return this.success('删除成功'); } diff --git a/src/api/controller/auth.js b/src/api/controller/auth.js index b95200c..ba2c7c1 100644 --- a/src/api/controller/auth.js +++ b/src/api/controller/auth.js @@ -18,10 +18,11 @@ export default class extends Base { return this.success(avatar_path); } - async loginAction() { + async loginByWeixinAction() { let code = this.post('code'); - let userInfo = this.post('userInfo'); + let fullUserInfo = this.post('userInfo'); + let userInfo = fullUserInfo.userInfo; //获取openid let options = { @@ -38,26 +39,32 @@ export default class extends Base { let sessionData = await rp(options); - //下载微信用户的头像到本地 - // let avatar_path = think.RESOURCE_PATH + '/static/user/avatar/1.' + _.last(_.split('https://img6.bdstatic.com/img/image/smallpic/liutaoxiaotu.jpg', '.')); - // rp('https://img6.bdstatic.com/img/image/smallpic/liutaoxiaotu.jpg').pipe(fs.createWriteStream(avatar_path)); sessionData = JSON.parse(sessionData); if (!sessionData.openid) { return this.fail('登录失败'); } - //根据openid查找用户是否已经注册 - let userId = await this.model('user').where({weixin_openid: sessionData.openid}).getField('id', true); + //验证用户信息完整性 + const crypto = require('crypto'); + const sha1 = crypto.createHash('sha1').update(fullUserInfo.rawData + sessionData.session_key).digest('hex'); + if (fullUserInfo.signature !== sha1) { + return this.fail('登录失败'); + } + + // 根据openid查找用户是否已经注册 + let userId = await this.model('user').where({ weixin_openid: sessionData.openid }).getField('id', true); if (think.isEmpty(userId)) { //注册 userId = await this.model('user').add({ - username: '微信用户' + sessionData.openid.substr(0, 6), + username: '微信用户' + think.uuid(6), password: sessionData.openid, register_time: parseInt(new Date().getTime() / 1000), register_ip: this.ip(), + last_login_time: parseInt(new Date().getTime() / 1000), + last_login_ip: this.ip(), weixin_openid: sessionData.openid, avatar: userInfo.avatarUrl, - sex: userInfo.gender, //性别 0:未知、1:男、2:女 + gender: userInfo.gender, //性别 0:未知、1:男、2:女 nickname: userInfo.nickName }); } @@ -65,22 +72,26 @@ export default class extends Base { sessionData.user_id = userId; //查询用户信息 - let newUserInfo = await this.model('user').field(['id', 'username', 'nickname', 'gender', 'avatar', 'birthday']).where({id: userId}).find(); + let newUserInfo = await this.model('user').field(['id', 'username', 'nickname', 'gender', 'avatar', 'birthday']).where({ id: userId }).find(); - let sessionKey = think.uuid(128); + //更新登录信息 + userId = await this.model('user').where({ id: userId }).update({ + last_login_time: parseInt(new Date().getTime() / 1000), + last_login_ip: this.ip(), + }); + + let TokenSerivce = this.service('token'); + let tokenObj = new TokenSerivce(); + let sessionKey = await tokenObj.create(sessionData); if (think.isEmpty(newUserInfo) || think.isEmpty(sessionKey)) { return this.fail('登录失败'); } - //保存openid到redis - await think.cache(sessionKey, sessionData, {timeout: 5400}); - - return this.success({token: sessionKey, userInfo: newUserInfo}); + return this.success({ token: sessionKey, userInfo: newUserInfo }); } async logoutAction() { - await think.cache(this.header('token'), null); return this.success(); } } \ No newline at end of file diff --git a/src/api/controller/base.js b/src/api/controller/base.js index 1c45bd9..1380b60 100644 --- a/src/api/controller/base.js +++ b/src/api/controller/base.js @@ -1,7 +1,26 @@ 'use strict'; export default class extends think.controller.base { + /** - * some base method in here + * 前置操作 */ + async __before() { + + think.token = this.header('X-Nideshop-Token') || ''; + if (!think.isEmpty(think.token)) { + let TokenSerivce = this.service('token'); + let tokenObj = new TokenSerivce(); + let sessionInfo = await tokenObj.parse(); + + console.log(sessionInfo) + if (!think.isEmpty(sessionInfo) && sessionInfo.user_id > 0) { + think.userId = sessionInfo.user_id; + } else { + think.userId = 0; + } + } else { + think.userId = 0; + } + } } \ No newline at end of file diff --git a/src/api/controller/cart.js b/src/api/controller/cart.js index a3a1036..697fcb0 100644 --- a/src/api/controller/cart.js +++ b/src/api/controller/cart.js @@ -9,7 +9,7 @@ export default class extends Base { * @returns {Promise.<{cartList: *, cartTotal: {goodsCount: number, goodsAmount: number, checkedGoodsCount: number, checkedGoodsAmount: number}}>} */ async getCart(){ - let cartList = await this.model('cart').where({user_id: 1, session_id: 1}).select(); + let cartList = await this.model('cart').where({user_id: think.userId, session_id: 1}).select(); //获取购物车统计信息 let goodsCount = 0; @@ -90,7 +90,7 @@ export default class extends Base { list_pic_url: goodsInfo.list_pic_url, number: number, session_id: 1, - user_id: 1, + user_id: think.userId, retail_price: productInfo.retail_price, market_price: productInfo.retail_price, goods_specifition_name_value: goodsSepcifitionValue.join(';'), @@ -238,7 +238,7 @@ export default class extends Base { let couponId = this.get('couponId'); //使用的优惠券id //选择的收货地址 - let checkedAddress = await this.model('address').where({is_default: 1}).find(); + let checkedAddress = await this.model('address').where({is_default: 1, user_id: think.userId}).find(); if ( !think.isEmpty(checkedAddress)) { checkedAddress.province_name = await this.model('region').getRegionName(checkedAddress.province_id); checkedAddress.city_name = await this.model('region').getRegionName(checkedAddress.city_id); @@ -256,7 +256,7 @@ export default class extends Base { }); - //获取可用的优惠券信息 + //获取可用的优惠券信息,功能还示实现 let couponList = await this.model('user_coupon').select(); let couponPrice = 0.00; //使用优惠券减免的金额 diff --git a/src/api/controller/collect.js b/src/api/controller/collect.js index 04405a8..8e2c5db 100644 --- a/src/api/controller/collect.js +++ b/src/api/controller/collect.js @@ -3,6 +3,13 @@ import Base from './base.js'; export default class extends Base { + + async __before() { + if (think.userId <= 0) { + return this.fail(401, '请先登录'); + } + } + /** * index action * @return {Promise} [] @@ -24,7 +31,7 @@ export default class extends Base { join: 'left', //join 方式,有 left, right, inner 3 种方式 as: 'g', // 表别名 on: ['c.value_id', 'g.id'] //ON 条件 - }).where({user_id: getLoginUserId(), type_id: typeId}).countSelect(); + }).where({user_id: think.userId, type_id: typeId}).countSelect(); return this.success(list); @@ -34,7 +41,7 @@ export default class extends Base { let typeId = this.post('typeId'); let valueId = this.post('valueId'); - let collect = await this.model('collect').where({type_id: typeId, value_id: valueId, user_id: 1}).find(); + let collect = await this.model('collect').where({type_id: typeId, value_id: valueId, user_id: think.userId}).find(); let collectRes = null; let handleType = 'add'; if (think.isEmpty(collect)) { @@ -42,7 +49,7 @@ export default class extends Base { collectRes = await this.model('collect').add({ type_id: typeId, value_id: valueId, - user_id: 1, + user_id: think.userId, add_time: parseInt(new Date().getTime() / 1000) }); } else { diff --git a/src/api/controller/goods.js b/src/api/controller/goods.js index d6b9b75..a269a7b 100644 --- a/src/api/controller/goods.js +++ b/src/api/controller/goods.js @@ -68,7 +68,7 @@ export default class extends Base { //当前用户是否收藏 - let userHasCollect = await this.model('collect').isUserHasCollect(1, 0, goodsId); + let userHasCollect = await this.model('collect').isUserHasCollect(think.userId, 0, goodsId); //记录用户的足迹 TODO await await this.model('footprint').addFootprint(goodsId); @@ -140,7 +140,7 @@ export default class extends Base { //添加到搜索历史 let keywords = await this.model('search_history').add({ keyword: keyword, - user_id: 1, + user_id: think.userId, add_time: parseInt(new Date().getTime() / 1000) }); diff --git a/src/api/controller/order.js b/src/api/controller/order.js index b9d37e1..5ef06db 100644 --- a/src/api/controller/order.js +++ b/src/api/controller/order.js @@ -21,7 +21,7 @@ export default class extends Base { */ async listAction() { - let orderList = await this.model('order').where({user_id: 1}).page(1, 10).countSelect(); + let orderList = await this.model('order').where({user_id: think.userId}).page(1, 10).countSelect(); let newOrderList = []; for (let item of orderList.data) { @@ -50,7 +50,7 @@ export default class extends Base { async detailAction() { let orderId = this.get('orderId'); - let orderInfo = await this.model('order').where({user_id: 1, id: orderId}).find(); + let orderInfo = await this.model('order').where({user_id: think.userId, id: orderId}).find(); if (think.isEmpty(orderInfo)) { return this.fail('订单不存在'); @@ -102,7 +102,7 @@ export default class extends Base { let freightPrice = 0.00; //获取要购买的商品 - let checkedGoodsList = await this.model('cart').where({user_id: 1, session_id: 1, checked: 1}).select(); + let checkedGoodsList = await this.model('cart').where({user_id: think.userId, session_id: 1, checked: 1}).select(); if (think.isEmpty(checkedGoodsList)) { return this.fail('请选择商品'); } @@ -130,7 +130,7 @@ export default class extends Base { let orderInfo = { order_sn: this.model('order').generateOrderNumber(), - user_id: 1, + user_id: think.userId, //收货地址和运费 consignee: checkedAddress.name, diff --git a/src/api/controller/search.js b/src/api/controller/search.js index acf3eba..fb674c6 100644 --- a/src/api/controller/search.js +++ b/src/api/controller/search.js @@ -13,7 +13,7 @@ export default class extends Base { //取出热闹关键词 let hotKeywordList = await this.model('keywords').distinct('keyword').field(['keyword', 'is_hot']).limit(10).select(); - let historyKeywordList = await this.model('search_history').distinct('keyword').where({ user_id: 1 }).limit(10).getField('keyword'); + let historyKeywordList = await this.model('search_history').distinct('keyword').where({ user_id: think.userId }).limit(10).getField('keyword'); return this.success({ defaultKeyword: defaultKeyword, @@ -30,7 +30,7 @@ export default class extends Base { } async clearhistoryAction() { - let historyKeywordList = await this.model('search_history').where({ user_id: 1 }).delete(); + let historyKeywordList = await this.model('search_history').where({ user_id: think.userId }).delete(); return this.success(); } } \ No newline at end of file diff --git a/src/api/service/token.js b/src/api/service/token.js new file mode 100644 index 0000000..fcac127 --- /dev/null +++ b/src/api/service/token.js @@ -0,0 +1,75 @@ +'use strict'; + +const jwt = require('jsonwebtoken'); + +const secret = think.config('session.secret'); + +export default class extends think.service.base { + /** + * init + * @return {} [] + */ + init(...args) { + super.init(...args); + } + + /** + * 根据header中的X-Nideshop-Token值获取用户id + */ + async getUserId() { + + const token = think.token; + + if (!token) { + return 0; + } + + let result = await this.parse(); + + if (think.isEmpty(result) || result.user_id <= 0) { + return 0; + } + + return result.user_id; + } + + /** + * 根据值获取用户信息 + */ + async getUserInfo() { + + let userId = await this.getUserId(); + if (userId <= 0) { + return null; + } + + let userInfo = await this.model('user').field(['id', 'username', 'nickname', 'gender', 'avatar', 'birthday']).where({ id: userId }).find(); + + return think.isEmpty(userInfo) ? null : userInfo; + } + + async create(userInfo) { + let token = jwt.sign(userInfo, secret); + return token; + } + + async parse() { + if (think.token) { + try { + return jwt.verify(think.token, secret); + } catch (err) { + return null; + } + } + return null; + } + + async verify() { + let result = await this.parse(); + if (think.isEmpty(result)) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/src/common/bootstrap/global.js b/src/common/bootstrap/global.js index db92d7b..956054a 100644 --- a/src/common/bootstrap/global.js +++ b/src/common/bootstrap/global.js @@ -22,5 +22,5 @@ global.getTime = function () { }; global.getLoginUserId = function () { - return 1; + return think.userId }; \ No newline at end of file diff --git a/src/common/config/config.js b/src/common/config/config.js index efb87cc..c1caf8a 100644 --- a/src/common/config/config.js +++ b/src/common/config/config.js @@ -3,13 +3,13 @@ * config */ export default { - //key: value - default_module: 'api', //设置默认模块 - deny_module_list: [], //设置禁用的模块 + //key: value + default_module: 'api', //设置默认模块 + deny_module_list: [], //设置禁用的模块 - cors:{ + cors: { origin: '*', methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', preflightContinue: false - } + }, }; \ No newline at end of file diff --git a/src/common/config/session.js b/src/common/config/session.js index 4aa738a..90472e0 100644 --- a/src/common/config/session.js +++ b/src/common/config/session.js @@ -7,7 +7,7 @@ export default { name: 'thinkjs', type: 'file', secret: 'T^%*$XC@', - timeout: 24 * 3600, + timeout: 30 * 24 * 3600, cookie: { // cookie options length: 32, httponly: true diff --git a/src/common/model/cart.js b/src/common/model/cart.js index 8a5d358..550c179 100644 --- a/src/common/model/cart.js +++ b/src/common/model/cart.js @@ -9,7 +9,7 @@ export default class extends think.model.base { * @returns {Promise.<*>} */ async getGoodsList(){ - return await this.model('cart').where({user_id: 1, session_id: 1}).select(); + return await this.model('cart').where({user_id: think.userId, session_id: 1}).select(); } /** @@ -17,7 +17,7 @@ export default class extends think.model.base { * @returns {Promise.<*>} */ async getCheckedGoodsList(){ - return await this.model('cart').where({user_id: 1, session_id: 1, checked: 1}).select(); + return await this.model('cart').where({user_id: think.userId, session_id: 1, checked: 1}).select(); } /** @@ -25,6 +25,6 @@ export default class extends think.model.base { * @returns {Promise.<*>} */ async clearBuyGoods(){ - return await this.model('cart').where({user_id: 1, session_id: 1, checked: 1}).delete(); + return await this.model('cart').where({user_id: think.userId, session_id: 1, checked: 1}).delete(); } } \ No newline at end of file