基于node.js和Cocos Creator的开发

基于Node.js和Cocos Creator的开发 -实现用户

2018-08-26  本文已影响16人  Woodlouse

一,重构用户创建

在上篇文章(https://www.jianshu.com/p/42bc94ab7f69)中我们实现了用户的创建功能,存储用户信息的时候只有一个用户信息表,用户信息表的键为user:[userId],是一个和用户ID相关的键。用户在登录的时候输入的是用户名,如何根据用户名找到其键值进而找到用户信息呢?
为了解决这个问题,我们需要在创建用户时需要创建一个用户名和用户ID的对应表,这样的话我们在注册时需要判断用户名是否已经注册过了。即在我们这个系统中用户名不可重复。
下面开始我们的改造:

user.createUser = function(userName, passWord, callBack) {
    
    var createUser = function(userId) {
         // 获取到用户ID后创建用户
         var userKey = constData.USER_BASEK_KEY + userId;
         var userData = {
             'name' : userName,
             'passWord' : passWord,
             'coin' : 0,
             'diamond' : 0,
             'head' : '',
             'friends':[]
         }

        //  数据库创建用户
         redisDB.hmset(userKey, userData, function(err, result) {
             var data = {
                 'userId' : userId,
                 'name' : userName,
                 'token' : ''
             }

            //  创建用户名和id的映射
            redisDB.hset(constData.UNAME_UID_MAP_KEY, userName, userId);

             if(err) {
                data = {
                    'error' : err,
                    'note' : 'create user error!!'
                }
                callBack(data);
                return;
             }
             callBack(data);
         })
    }

    var getUserId = function() {
        redisDB.incrby(constData.GLOBAL_USER_ID, 1, function(err, userId) {
            if(err) {
                var data = {
                    'error' : err,
                    'note' : 'create user error!!'
                }
                callBack(data);
                return;
            }
    
            createUser(userId);
        });
    }

    // 检验用户名是否存在
    redisDB.hget(constData.UNAME_UID_MAP_KEY, userName, function(err, result) {
        if(result) {
            data = {
                'error' : 1,
                'note' : 'UserName exist'
            }
            callBack && callBack(data);
            return;
        }
        
        getUserId();
    });
}

这样,在登录的时候我们可以根据用户名找到用户ID,进而找到所有的用户信息。

二,开发前端登录功能

1, UI

登录UI包含以下几个控件:

2,代码开发
var http = require('http');
var Constant = require('Constant');

定义相关变量引用:

passWordOrUserNameIsNull: {
    default: null,
    type: cc.Label
},
passWordErrorHint: {
    default: null,
    type: cc.Label
},
userName: '',
passWd: ''

在定义上相关变量后,在编辑器中进行变量和控件的对应关系操作。

进行输入用户名/密码完毕后的操作:

inputUserNameEnded: function(editbox, customEventData) {
    this.userName = editbox.string;
},

inputPassWordEnded: function(editbox, customEventData) {
    this.passWd = editbox.string;
},

再将其和编辑器中的控件对应起来。

实现输入错误时的提示函数:

_showErrorHint: function(label) {
    this.passWordErrorHint.node.active = false;
    this.passWordOrUserNameIsNull.node.active = false;

    // 显示提示
    label.node.active = true;

    // 设置计时器
    this.scheduleOnce(function(){
        label.node.active = false;
    }.bind(this), 2);
},

登录按钮测回调函数

onLogin: function() {
    if (!this.userName || this.userName.length<1) {
        console.log('onLogin come in 000');
        this._showErrorHint(this.passWordOrUserNameIsNull);
        return;
    }

    if (!this.passWd || this.passWd.length<1) {
        console.log('onLogin come in 001 this.passWd = ' + this.passWd);
        this._showErrorHint(this.passWordErrorHint);
        return;
    }

    this._startLogin();
},

将其和登录按钮对应起来。
登录函数的实现

_startLogin: function() {
    var obj = {
        'url' : Constant.LOGIN_URL,
        'data' : {
            'userName' : this.userName,
            'passWord' : this.passWd
        },
        'success' : function(jsonData) {
            this._onLoginSuccess(jsonData);
        }.bind(this),

        'fail' : function() {
            this._onLoginFail(jsonData);
        }.bind(this)

    }
    
    http.request(obj);
},

登录回调函数的实现
本次只把登录结果信息打印出来:

_onLoginSuccess: function(jsonData) {
    console.log('_onLoginSuccess come in jsonData = ' + JSON.stringify(jsonData));
},

_onLoginFail: function(jsonData) {
    console.log('_onLoginFail come in jsonData = ' + JSON.stringify(jsonData));
},

三,后端功能实现

1,实现生成token功能
在constData.js中添加用户ID和token映射的键:
'USER_TOKEN_KEY' : 'uid:token'
此键对应的值为hash,field为用户ID,值为用户的token。
我们的token使用一组随机数加用户ID和时间等信息组成:

var randomInt = function() {
    return Math.ceil(Math.random() * 9999999);
}

var formatDate = function() {
    var d = new Date();
    return d.getFullYear() + '-' + d.getMonth() + '-' + d.getDay() + ' ' + d.getHours()+':'+d.getMinutes()+':'+d.getSeconds() + ' ' + d.getMilliseconds();
}

var setToken = function(userId) {
    var token = '' + randomInt() + '|' + userId + '|' + randomInt() + '|' + formatDate() + '|' + randomInt();
    redisDB.hset(constData.USER_TOKEN_KEY, userId, token);
    return token;
}

2,实现用户登录逻辑
在用户登录时我们后端需要做的事:

user.login = function(userName, passWord, callBack) {
    redisDB.hget(constData.UNAME_UID_MAP_KEY, userName, function(err, result) {
        if(!result) {
            data = {
                'error' : 1,
                'note' : 'UserName not exist'
            }
            callBack && callBack(data);
            return;
        }

        // 获取用户
        var userKey = constData.USER_BASEK_KEY + result;
        var dataElements = ['passWord', 'name', 'coin', 'diamond', 'head', 'friends'];
        redisDB.hmget(userKey, dataElements, function(err, result) {
            if (err) {
                var data  = {
                    'error' : 1,
                    'note' : 'get userinfo error!'
                }
                callBack && callBack(data);
                return;
            }

            //判断用户密码是否相同
            var userData = {};
            for(var i=0, l=dataElements.length; i<l; i++) {
                userData[dataElements[i]] = result[i];
            }
            // 设置用户token
            userData['token'] = setToken(result);

            if(userData['passWord'] == passWord) {
                var data = {
                    'error' : 0,
                    'data' : userData
                }
                callBack && callBack(data);
                return;
            }
            data = {
                'error' : 1,
                'note' : 'Error password'
            }
            callBack && callBack(data);
        });
    });
}

3,路由映射
在router.js中添加登录功能的处理:

router.login = function(req, res, callBack) {
    var params = getParams(req);
    //登录
    user.login(params['userName'], params['passWord'], function(data) {
        callBack && callBack(data);
    })
}

至此,我们就完成了用户登录过程。


代码在这儿


上一篇 实现用户注册
下一篇 实现Socket通信

上一篇 下一篇

猜你喜欢

热点阅读