美文网首页基于node.js和Cocos Creator的开发
基于Node.js和Cocos Creator的开发 -实现用户

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

作者: Woodlouse | 来源:发表于2018-08-26 15:41 被阅读16次

    一,重构用户创建

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

    • 定义用户名和用户ID映射键
      在constData.js中添加一行定义:
      'UNAME_UID_MAP_KEY' : 'uname:uid',
      此键值对应值的数据结构为hash,field为用户名,value为userId。
    • 重构创建用户函数
      在创建用户时首先检测是否已经存在用户名和用户ID的对应关系了,如果存在则此用户名不可用,不存在则创建用户,同时记录用户名和用户ID的对应关系。
      在user.js中重构createUser如下:
    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包含以下几个控件:

    • 用户名输入框
    • 密码输入框
    • 登录按钮
    • 输入错误提示信息
      如下图所示:


      01.png
    2,代码开发
    • 定义登录路径
      在Conatnt.js中加入以下定义:
      Constant.LOGIN_URL = baseURL + 'login/';
    • 登录逻辑开发
      在Script/Scene文件夹下新建login.js文件,首先引入文件:
    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,实现用户登录逻辑
    在用户登录时我们后端需要做的事:

    • 根据用户名找到用户ID
    • 根据用户ID找到用户信息
    • 判断用户输入的密码和找到的用户信息中存储的用户密码是否一致
    • 返回结果
      在user.js文件中添加入如下函数
    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通信

    相关文章

      网友评论

        本文标题:基于Node.js和Cocos Creator的开发 -实现用户

        本文链接:https://www.haomeiwen.com/subject/gxxpiftx.html