2012-05-15 3 views
1

socketIO를 통해 MySQL DB를 통해 인증을 시도하고 있습니다. 연결을 설정하고 아무런 문제없이 결과를 쿼리 할 수는 있지만 어떤 이유로 사용자가 인증되었는지 여부를 socketio의 connection 부분으로 전달할 수 없습니다. 내 앱에 호스트 및 뷰어가 있다는 아이디어가 있습니다. QueryString에 비밀번호를 전송하지 않고 앱에 연결하면 앱은 뷰어로 간주되어 연결을 수락합니다. 암호가 전송되면 DB와 대조하여 연결을 허용/거부합니다. 변수를 connection에 전달하여 내 앱 이벤트 내부에서 사용할 수있게하려고합니다. 여기에 내가 지금까지 가지고있는 것이 있지만 분명히 data.query['ishost']은 앱에 전달되지 않습니다. data.query에 쓰기SocketIO + MySQL 인증

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); 
    }); 
}); 

는 handshakeData를 통해 액세스 할 수 있습니다. 하지만 어떤 이유로 애플 리케이션을 통과하지 못했습니다. 도움이된다면 고맙습니다.

답변

5

요청 문자열 매개 변수를 설정하는 것보다 요청 헤더를 설정하는 것이 좋습니다. 권한 부여 함수의 변수 data은 사용할 수있는 요청 헤더 및 쿠키 정보가 들어있는 핸드 셰이크 데이터입니다. 여기 쿠키 설정을 가진 예 : 당신이 socket.connect 전화하기 전에 클라이언트

는 서버

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); 
     } 
    }); 
}); 

, 당신의 인증/사용자 정보와 쿠키를 설정 :

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); 

브라우저가 btoa()을 지원하지 않는 한 클라이언트 측에서 Base64 라이브러리가 필요합니다.

이것은 중요한 인증 구조가 아닙니다. 쿼리 문자열이나 헤더 정보에서 사용자 자격 증명을 그대로 전달하는 것은 안전하지 않습니다. 이 방법을 사용하면 더 안전한 방법을 찾을 수 있습니다. passport.js 또는 everyauth와 같은 인증 라이브러리를 살펴 보는 것이 좋습니다. 이 코드에 서브 - 인 (Sub-in)하여 수표의 실행에 라이브러리가 저장하는 세션 정보를 활용할 수 있습니다.

+0

위대한 작품. 나중에 여권을 살펴볼거야 .js. 당신의 도움을 주셔서 감사합니다. –

+0

플래시 소켓으로 돌아 가면이 기능을 사용할 수 있습니까? – NightWolf

+0

잘 모르겠습니다. 저는 일반적으로 플래시 소켓을 피하여 서버 구성을 간소화합니다. –

관련 문제