SocketIO + MySQL 认证 [英] SocketIO + MySQL Authentication

查看:18
本文介绍了SocketIO + MySQL 认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 socketIO 对 MySQL 数据库进行身份验证.我已经建立了连接并且可以毫无问题地查询结果,但是由于某种原因,我无法将用户是否通过身份验证传递到 socketio 的 connection 部分.这个想法是我的应用程序有主机和查看器.如果连接到应用程序而未在 QueryString 中发送密码,则应用程序假定其为查看器并接受连接.如果发送了密码,则会根据 DB 进行检查并接受/拒绝连接.我想要一个变量传递到 connection 以便我可以在我的应用程序事件中使用它.这是我到目前为止所拥有的,但显然 data.query['ishost'] 没有传递到应用程序中.

I am trying to authenticate over a MySQL DB via socketIO. I have established the connection and can query results without an issue, but for some reason I cannot pass whether or not the user is authenticated into the connection part of socketio. The idea is my app has hosts and viewers. If connecting to the app without sending a password in the QueryString the app assumes its a viewer and accepts connection. If a password is sent, it is checked against the DB and accepts/rejects the connection. I want a variable to pass into the connection so I can use it inside of my apps events. Here's what I have so far but apparently the data.query['ishost'] isn't passing into the app.

sio.configure(function() {
    sio.set('authorization', function (data, accept) {
        UserID = data.query['username'];

        try {
            UserID = UserID.toLowerCase();
        } catch(err) {
            return accept("No WebBot Specified. ("+err+")", false);
        }

        // if not sending a password, skip authorization and connect as a viewer
        if (data.query['password'] === 'undefined')
        {
            return accept(null, true);
        }
        // if sending a password, attempt authorization and connect as a host
        else
        {
            client.query(
            'SELECT * FROM web_users WHERE username = "'+UserID+'" LIMIT 1',
              function selectCb(err, results, fields) {
                if (err) {
                  throw err;
                }
                // Found match, hash password and check against DB
                if (results.length != 0)
                {
                    // Passwords match, authenticate.
                    if (hex_md5(data.query['password']) == results[0]['password'])
                    {
                        data.query['ishost'] = true;
                        accept(null, true);
                    }
                    // Passwords don't match, do not authenticate
                    else
                    {
                        data.query['ishost'] = false;
                        return accept("Invalid Password", false);
                    }
                }
                // No match found, add to DB then authenticate
                else
                {
                    client.query(
                        'INSERT INTO web_users (username, password) VALUES ("'+UserID+'", "'+hex_md5(data.query['password'])+'")', null);

                    data.query['ishost'] = "1";
                    accept(null, true);
                }

                client.end();
              }
            );

            // Should never reach this
            return accept("Hacking Attempt", false);
        }

        // Definitely should never reach this
        return accept("Hacking Attempt", false);
    });
});

写入data.query 使其可通过handshakeData 访问.但由于某种原因,它没有通过应用程序传递它.感谢您提供任何帮助,谢谢.

Writing to the data.query makes it accessible through handshakeData. But for some reason its not passing it through the app. Any help is appreciated, thank you.

推荐答案

虽然我建议设置请求标头而不是设置查询字符串参数,但您已经很接近了.您的授权函数中的 data 变量是握手数据,其中包含您可以使用的请求标头和 cookie 信息.这是设置 cookie 的示例:

You're close, though I'd recommend setting a request header over setting a query string param. The data variable in your authorization function is handshake data that contains request header and cookie information you can use. Here's an example with setting a cookie:

在服务器上

io.configure(function() {
    io.set('authorization', function(handshake, callback) {
        var cookie, token, authPair, parts;

        // check for headers
        if (handshake.headers.cookie && 
            handshake.headers.cookie.split('=')[0]=='myapp') {

            // found request cookie, parse it
            cookie   = handshake.headers.cookie;
            token    = cookie.split(/s+/).pop() || '';
            authPair = new Buffer(token, 'base64').toString();
            parts    = authPair.split(/:/);

            if (parts.length>=1) {
                // assume username & pass provided, check against db
                // parts[0] is username, parts[1] is password
                // .... {db checks}, then if valid....
                callback(null, true);
            } else if(parts.length==1) {
                // assume only username was provided @ parts[0]
                callback(null,true);
            } else {
                // not what we were expecting
                callback(null, false);
            }
        }
        else {
            // auth failed
            callback(null, false);
        }
    });
});

在客户端

调用 socket.connect 之前,使用您的身份验证/用户信息设置 cookie:

Before you call socket.connect, set a cookie with your auth / user info:

function writeCookie(value, days) {
    var date, expires;

    // days indicates how long the user's session should last
    if (days) {
        date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        expires = "; expires="+date.toGMTString();
    } else {
        expires = "";
    }
    document.cookie = "myapp="+Base64.encode(value)+expires+"; path=/";
};

// for a 'viewer' user:
writeCookie('usernameHere', 1);

// for the 'host' user:
writeCookie('usernameHere:passwordHere', 1);

除非您的浏览器支持 ,否则您需要在客户端使用 Base64 库btoa().

You'll need a Base64 library on the client side unless your browser supports btoa().

需要注意的是,这不是一个好的身份验证结构.直接在查询字符串或标头信息中传递用户凭据是不安全的.不过,这种方法可以让您更接近一种更安全的方法.我建议查看像passport.js 或everyauth 这样的auth 库.您可以嵌入此代码以利用这些库存储的会话信息来运行您的检查.

It's important to note that this isn't a good authentication structure. Passing user credentials straight in either query strings or header information is not secure. This method gets you closer to a more secure method, though. I'd recommend looking into an auth library like passport.js or everyauth. You can sub-in this code to utilize the session information those libraries store in running your checks.

这篇关于SocketIO + MySQL 认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆