本节我们给 Socket.io加上 安全套。 大家都知道 Socket.io 要是不做验证的话,大家都可以访问到。在这实际的生产环境中是 绝对不容许的。 我们就用Socket.IO 自带的 Authorization 给 Socket.IO 做一个 安全效验!我们先上图
现在代码中添加对 require('socketio-auth') 的引用。
运行出现下图的报错了 是没有添加 Socket-auth 库
第一步先把 socketio-auth 下载下来 然后 就可以 跑起来了。
主要参考地址:https://cnodejs.org/topic/55a66ddd5a4b4a86539c2fe6 (有可能是版本原因,没有成功)
后来参照 GitHub https://github.com/facundoolano/socketio-auth
才完成需求
服务器端:
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
module.exports = require('./lib/express');
var io = require('socket.io')({
transports: ['websocket'],
});
require('socketio-auth')(io, {
authenticate: authenticate,
postAuthenticate: postAuthenticate,
disconnect: disconnect,
timeout: 10000
});
io.attach(4567);
console.log('Server Start....');
var socketArray = {};//Socket ����
io.on('connection', function (socket) {
console.log('Client Contect. SocketID:'+socket.id);
//socket.emit('SocketProtocol.Info', { hi: 'Hello,world' });
socket.emit('SocketProtocol.Info', "ConnectServer Scuess! :"+socket.id);
socket.on('SocketProtocol.Login', function (data) {
console.log(data);
//var content = JSON.parse(data);
socket.nickName = data.nickName;
socket.guid = data.guid;
//
if( !socketArray.hasOwnProperty(socket.guid) )
{
socketArray[socket.guid] = data;
}
//
//console.log(socketArray);
var chatContent={};
chatContent.nickName = socket.nickName;
chatContent.chatMessage = "Login Scuess";
socket.emit('SocketProtocol.Login',chatContent);
});
socket.on('SocketProtocol.Chat', function (data) {
//console.log("SocketProtocol.Chat:"+data);
var chatContent ={};
chatContent.nickName = socket.nickName;
chatContent.chatMessage = data.chatMessage;
console.log("chatContent.toJSON():"+JSON.stringify(chatContent));
io.sockets.emit('SocketProtocol.Chat',chatContent);//All SocketUsers
//socket.broadcast.emit(data);//All SocketUsers But Self
});
socket.on('disconnect', function () {
console.log("disconnect");
if( socketArray.hasOwnProperty(socket.guid) )
{
delete socketArray[socket.guid];
console.log("disconnect Delete:"+socket.guid);
}
console.log("Inline Count:"+countProperties(socketArray));
});
});
function countProperties (obj) {
var count = 0;
for (var property in obj) {
if (Object.prototype.hasOwnProperty.call(obj, property)) {
count++;
}
}
return count;
}
this.size = function () {
var count = 0;
for (var prop in items) {
if (items.hasOwnProperty(prop)) {
++count;
}
}
return count;
};
function authenticate(socket, data, callback) {
console.log("authenticate");
var username = data.username;
var password = data.password;
console.log("authenticate:username: "+username);
console.log("authenticate:password: "+password);
//db.findUser('User', {username:username}, function(err, user) {
// if (err || !user)
// {
// return callback(new Error("User not found"));
// }
// return callback(null, user.password == password);
//});
//两种回传方式 例子中是通过数据库的方式判断的。在这里 我们就模拟了 验证成功和失败两种
return callback(null,"OK! Scuess!");
//return callback(new Error("Fail"));
}
function postAuthenticate(socket, data) {
//var username = data.username;
//
//db.findUser('User', {username:username}, function(err, user) {
// socket.client.user = user;
//});
console.log("postAuthenticate");
var user = {};
user.username = data.username;
user.password = data.password;
socket.client.user = user;
}
function disconnect(socket) {
console.log(socket.id + ' disconnected');
}
function ShowObjectProty(date) {
for (var item in date){
console.log(date[item]);
}
}
客户端
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SocketIO;
using System;
using LitJson;
public class SocketController : MonoBehaviour {
SocketIOComponent socketIO;
private bool login;
private string chatMessage = "";
private string chatContent = "";
private string nickName = "";
private Guid guid = Guid.NewGuid();
// Use this for initialization
void Start ()
{
GameObject go = GameObject.Find("SocketIO");
if (go == null)
{
go = new GameObject("SocketIO");
socketIO = go.AddComponent<SocketIOComponent>();
}
else
{
socketIO = go.GetComponent<SocketIOComponent>();
if (socketIO == null)
{
socketIO = go.AddComponent<SocketIOComponent>();
}
}
socketIO.url = "ws://192.168.0.170:4567/socket.io/?EIO=3&transport=websocket";
socketIO.Connect();
socketIO.socket.OnOpen += (object sender, EventArgs e) =>
{
Dictionary<string, string> data = new Dictionary<string, string>();
data["username"] = "John";
data["password"] = "secret";
socketIO.Emit("authentication", new JSONObject(data));
};
OnAddEvemt();
}
private void OnGUI()
{
if (!login)
{
Rect rect = new Rect(Screen.width / 3, Screen.height / 3, Screen.width / 3, Screen.height / 2);
GUI.Box(rect, "" );
GUI.Label(new Rect(rect.x + Screen.width / 60, rect.y + Screen.height / 9, rect.width - Screen.width / 15, Screen.height / 15),"请输入昵称:");
nickName = GUI.TextField(new Rect(rect.x + Screen.width / 10, rect.y+ Screen.height / 10, rect.width- Screen.width / 5, Screen.height / 15), nickName);
if( GUI.Button(new Rect(rect.x + Screen.width / 30, rect.y + Screen.height/4, rect.width - Screen.width / 15, Screen.height / 15),"登录" ))
{
if (nickName.Length > 0)
{
Dictionary<string, string> data = new Dictionary<string, string>();
data["guid"] = guid.ToString();
data["nickName"] = nickName;
socketIO.Emit(SocketIOProtocol.ProtocolLogin, new JSONObject(data));
}
}
return;
}
GUI.Label(new Rect(0, 0, Screen.width, Screen.height - 200), chatContent);
chatMessage = GUI.TextField(new Rect(0, Screen.height - 200, Screen.width - 200, 200), chatMessage);
if (GUI.Button(new Rect(Screen.width - 200, Screen.height - 200, 200, 200), "Send"))
{
Dictionary<string, string> data = new Dictionary<string, string>();
data["chatMessage"] = chatMessage;
socketIO.Emit(SocketIOProtocol.ProtocolChat, new JSONObject(data));
chatMessage = string.Empty;
}
}
void OnAddEvemt()
{
socketIO.On("authenticated", (data)=> {
// use the socket as usual
Debug.Log("use the socket as usual");
Debug.Log("authenticated, 验证成功" + data.data);
});
socketIO.On("unauthorized", (data) => {
// use the socket as usual
Debug.Log("unauthorized 验证失败,"+data.data);
});
socketIO.On(SocketIOProtocol.ProtocolLogin, (date) =>
{
JsonData jsonData = JsonMapper.ToObject(date.data.ToString());
string message = string.Format("{0} : {1}", jsonData["nickName"], jsonData["chatMessage"]);
chatContent += message + "\r\n";
login = true;
});
socketIO.On(SocketIOProtocol.ProtocolChat, (date) =>
{
JsonData jsonData = JsonMapper.ToObject(date.data.ToString());
string message = string.Format("{0} : {1}", jsonData["nickName"], jsonData["chatMessage"]);
chatContent += message + "\r\n";
});
socketIO.On(SocketIOProtocol.ProtocolInfo, (date) =>
{
Debug.Log(date.data);
});
}
void OnRemoveEvent()
{
socketIO.Off(SocketIOProtocol.ProtocolLogin);
socketIO.Off(SocketIOProtocol.ProtocolChat);
socketIO.Off(SocketIOProtocol.ProtocolInfo);
}
}
Dome 下载地址:https://download.csdn.net/download/nicepainkiller/10502356
到这里。 Socket.IO for Unity3D 已经告一段落了。
等有时间 可以做下 Node.JS For Nginx 的分布式。以及 RPG 小游戏