Diego Uribe Gamez
Posted on October 18, 2019
One of my abilities is to use socket.io along with a backend application (In this case, it is Django) to send real time events to the web browser.
The key is to use socket.io as a bridge of events without over-optimizing the infrastructure, by not handling the business logic on this bridge.
To perform this, It is necessary to follow the following steps:
- The user log in to the web application, when the backend dispatches the HTML access.
- The web application have to request access to the socket server.
- The socket server have to verify the authenticity of the user that is longing in with the backend.
Let’s do it.
The user log in to the web application, when the backend dispatches the HTML access.
Ok, At first the backend sends the django user to redis in a temporarily form, and secures it with a key.
Then, it dispatches the HTML along with the cookie that contains the key hat we used to secure the user in redis, giving as a result our template, as follows:
class IndexTemplateView(TemplateView):
template_name = 'base.html'
def get_context_data(self, **kwargs):
context = super(IndexTemplateView, self).get_context_data(**kwargs)
self.set_access_token()
data = {
'title': 'Connect nodejs with your app'
}
context.update(data)
return context
def set_access_token(self):
self.token = get_random_string(32)
key = 'session:%s' % str(self.token)
data = {
'user': 'diegoug'
}
value = json.dumps(data)
redis.setex(key, 86400, value)
def render_to_response(self, context, **response_kwargs):
response = super(IndexTemplateView, self).render_to_response(context, **response_kwargs)
response.set_cookie(key='nodejskey', value=self.token, max_age=86400, domain=os.environ.get('DJANGO_SERVER_NAME', ''), secure=None)
return response
The web application have to request access to the socket server.
This step is the simplest, here the HTML javascript accesses the socket server and when it accesses correctly, it displays the user name on the screen. Here the HTML code:
<script src="{{request.socketio}}/socket.io/socket.io.js"></script>
<script type="text/javascript">
window.nodeServer = '{{request.socketio}}';
</script>
<script>
const socket = io(window.nodeServer);
socket.on('join', data => {
let string = 'message: '+ data + '<br>';
document.getElementById('data').innerHTML += string;
});
</script>
<h1>{{ title }}</h1>
<div id="data"></div>
The socket server have to verify the authenticity of the user that is longing in with the backend.
At this point the socket server have to take the key from the cookie and take out the data of redis, if this data exists, it allows the socket to access to the connection event, sending an event to a channel that notify the user.
// dependencies
const Io = require('socket.io');
const redis = require('redis');
const cookie = require('cookie');
const serialize = require('node-serialize');
const clientRedis = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_HOST);
clientRedis.select(1);
// module
function Socket () {
this.io = Io.listen(process.env.SOCKETIO_PORT);
}
// run socket
Socket.prototype.run = function () {
// set auth
this.io.use((socket, next) => {
this.auth(socket, next);
});
// when a client connects
this.io.sockets.on('connection', socket => {
// event join
socket.emit('join', socket.handshake.user);
});
};
// authentication
Socket.prototype.auth = function (socket, next) {
// get cookie token
const userCookie = cookie.parse(socket.request.headers.cookie);
// redis validation
clientRedis.get('session:' + userCookie.nodejskey, (err, session) => {
// error or not session
if (err || !session) {
return next(new Error('Not authorized.'));
}
// config session
session = serialize.unserialize(session);
socket.handshake.user = session.user;
next();
});
};
let socket = new Socket();
socket.run();
From here and on, it is a matter of managing rooms, direct messages and keep using redis to send events between the backend and the socket server using channels.
An important step that needs to be done, is to verify the domain from where the user try to log in the socket, to avoid impersonation of the real user identity.
Posted on October 18, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.