Etherpad-Lite 使用 Radius 认证

来源:互联网 发布:mac版 chrome 编辑:程序博客网 时间:2024/06/01 08:34

最近打工的地方要求写一个插件给Etherpad-Lite 提供 Radius 的认证方式, 经过筛选后选择了node js 的一个Radius 库, 代码的实现中也有用到node js 的一个async的库作为数据库处理同步的方法。我自己的系统环境是Linux Mint 17, 希望能够为有这方面需求的朋友提供一些方便, 自己以前没有接触过JavaScript也希望大家能够不吝指教。

关于Etherpad-Lite的介绍在 http://etherpad.org/

关于Etherpad-Lite的安装在 https://help.ubuntu.com/community/Etherpad-liteInstallation

关于使用的node js 的两个库分别在 https://github.com/retailnext/node-radius 和 https://github.com/caolan/async

我的Radius认证方式实在Etherpad-Lite的插件user_pad和user_pad_frontend上实现的。其实我只是做了以下的修改:


I. Radius 库函数, 主要是为了让返回值为数字, 不知道是我自己处理错误还是怎样,返回字符时候总是出错.

     Original:    //var ret = {};    //ret.code = code_map[packet.readUInt8(0)];     Changed:    var ret = {};    ret.code = packet.readUInt8(0);


II. 插件user_pad_frontend中的hooks.js  和 register.js

hooks.js 中主要是改了registerUser, login, 和 userAthentication方法。

1. registerUser,

由于我们没有register的需求,所以我把这一部分邮件注册的功能删除了。由于我们的Radius数据库在LDAP中,我们Etherpad-Lite只是来保存用户名,密码没有要求,只要Radius认证成功,就在数据库中创建用户,让后默认其他属性。更改后的代码如下:

//register user who are not in database    var registerUser = function (user, cb) {        var existUser = "SELECT * from User where User.name = ?";        var retValue = existValueInDatabase(existUser, [user.email], function (exists) {            if (exists) {                //cb(false, USER_EXISTS);                cb(true, null);            } else {                getPassword(function (consString) {                    createSalt(function (salt) {                        encryptPassword(user.password, salt, function (encrypted) {                            var addUserSql = "INSERT INTO User VALUES(null, ?,?, 0, 0, ?,?,?,1)";                            var addUserQuery = connection.query(addUserSql, [user.email, encrypted, user.fullname, consString, salt]);                            addUserQuery.on('error', mySqlErrorHandler);                            addUserQuery.on('result', function (newUser) {                                connection.pause();                                checkInvitations(user.email, newUser.insertId, function () {                                    addUserToEtherpad(newUser.insertId, function (){                                        connection.resume();                                    });                                });                            });                            addUserQuery.on('end', function () {                                cb(true, null);                            });                        });                    });                });            }            return exists;        });        return retValue; // return status of function call    };

2.  login 一块有用到上面提到的node js 的async模块, 代码如下:

//login part, for user, first time, needs to be register in database,     args.app.post('/login', function (req, res) {        new formidable.IncomingForm().parse(req, function (err, fields) {            if (!fields.email) {                sendError('No valid E-mail Address given', res);                return false;            } else if (!fields.password) {                sendError('No password given', res);                return false;            }            var email = fields.email;            var password = fields.password;            var retVal = userAuthentication(email, password, function (success, user, userFound, considered, active) {                if (success) {//register user before loginvar user_new = {};user_new.fullname = email;user_new.email = email;user_new.password = password;user_new.passwordrepeat = password;user_new.location = fields.location;registerUser(user_new, function (success, error) {if (!success) {sendError(error, res);} else {//Select User Id, use async moduleconsole.log('Register user successful!!!');async.parallel([function(callback){var idQuery="SELECT * FROM User WHERE name = ?";connection.query(idQuery, [email], function(err, result){if (err) callback(err,null);elsecallback(null,result);});}],function(err,result){if (err) {console.log("ERROR : ",err);            } else {            req.session.userId=(result[0][0].userID).toString();req.session.username=email;req.session.email = email;req.session.password = password;req.session.baseurl = fields.url;var data = {};data.success = true;res.send(data);console.log("result from db is : ",result);//console.log("db user id is: ", (result[0][0].userID).toString());return true;}     });}});                  } else {                    if (!active) {                        sendError('User is inactive', res);                    }                    else if (!userFound || considered) {                        sendError('User or password wrong!', res);                    }                    else if (userFound && !considered) {                        sendError('You have to confirm your registration!', res);                    }                    return false;                }            });            return retVal;        });    });

3. userAuthentication 主要是用了Radius的认证,使用了node js 的 radius 模块。代码如下:

//user authentication var userAuthentication = function(username, password, cb){ var client=dgram.createSocket("udp4"); client.bind(49001); console.('debug', 'userAuthentication'); var encoded=packetSend(username, password);         client.send(encoded, 0, encoded.length, 1812, '127.0.0.1'); var sent = false;    var userFound = false;         var considered = false;         var active = true;     //Client Receive Response          client.on('message', function(msg, rinfo){                 console.log('Client receiving......!......!......');                 var response = authRadius.decode({packet: msg, secret: secret}); var request = sent_packets[response.identifier]; var valid_response = authRadius.verify_response({ response: msg, request: request.raw_packet, secret: request.secret }); if (valid_response) { if(response.code==2){ //表示认证Accept, 就是前面更改Radius模板代码之后的返回值userFound = true;sent = true;console.log('Response Access-Accept from Radius Authentication');console.log(msg);cb(true, userFound, null, considered);console.log('You should not implement here!');}else{console.log('Response Access-Reject from Radius Authentication');cb(false, null, userFound, considered, active);console.log('You should not implement here!');}}else{console.log('WARNING: Got invalid response '); //(shared secret may be incorrect);cb(false, null, userFound, considered, active);console.log('You should not implement here!');}client.close();});};

这里要注意的是每次都要关闭client, 要不然Radius 服务器会发送多个回复,如果不关闭容易跟后面的混在一起,导致用户在数据库创建不能正常。






0 0