实现内容:
纯文字聊天
前端使用AES加密聊天,可以结合TLS加密传输
方便分享聊天室链接
服务器只作为转发,其转发内容均为加密内容
本文只作为学习用途
后端代码
import express from 'express';
import { createServer } from 'node:http';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { Server } from 'socket.io';
const app = express();
const server = createServer(app);
const io = new Server(server);
const __dirname = dirname(fileURLToPath(import.meta.url));
app.get('/', (req, res) => {
res.sendFile(join(__dirname, 'index.html'));
});
io.on('connection', (socket) => {
socket.join(socket.handshake.auth.room)
socket.on('chat', (msg) => {
io.to(socket.handshake.auth.room).emit('chat', msg);
});
});
server.listen(3000, () => {
console.log('server running at http://localhost:3000');
});
前端HTML
Chat
<script src="https://cdn.staticfile.net/socket.io/4.8.1/socket.io.min.js"></script>
<script src="https://cdn.staticfile.net/crypto-js/4.2.0/crypto-js.min.js"></script>
<script>
let room = getQueryParam('r')
let key = getQueryParam('k')
if (!room) room = generateUUID();
if (!key) key = generateRandomHex();
history.replaceState({}, '', `?r=${room}&k=${key}`);
let name = 'Anonymous'
name = window.prompt('Name', name);
document.getElementById('copy').addEventListener('click', ()=>{
let textToCopy = window.location.href;
link(textToCopy);
});
function link(textToCopy) {
const textArea = document.createElement('textarea');
textArea.value = textToCopy;
document.body.appendChild(textArea);
textArea.select();
textArea.setSelectionRange(0, 99999);
document.execCommand('copy');
document.body.removeChild(textArea);
alert('Copied');
}
function getQueryParam(paramName) {
const queryString = window.location.search;
const params = new URLSearchParams(queryString);
return params.get(paramName);
}
function generateRandomHex() {
let hex = '';
const characters = '0123456789ABCDEF';
for (let i = 0; i < 32 i hex characters.length return hex function encrypttext const encrypted='CryptoJS.AES.encrypt(text,' key.tostring return encrypted function decryptencryptedtext const bytes='CryptoJS.AES.decrypt(encryptedText,' key const decrypted='bytes.toString(CryptoJS.enc.Utf8);' return decrypted function generateuuid return 1e7 -1e3 -4e3 -8e3 -1e11.replace018g>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
function getdate() {
const currentDate = new Date();
const hours = String(currentDate.getHours()).padStart(2, '0');
const minutes = String(currentDate.getMinutes()).padStart(2, '0');
const seconds = String(currentDate.getSeconds()).padStart(2, '0');
const formattedTime = `${hours}:${minutes}:${seconds}`;
return formattedTime;
}
const socket = io('/', { auth: { room: room }, transports: ["websocket"] });
const form = document.getElementById('form');
const input = document.getElementById('input');
const messages = document.getElementById('messages');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value) {
data = JSON.stringify({ name: name, messages: input.value })
const encrypted = encrypt(data);
socket.emit('chat', encrypted);
input.value = '';
}
});
socket.on('chat', (msg) => {
const data = decrypt(msg);
if (data == '') return false;
const json = JSON.parse(data);
if (!json) return false;
color = '#000'
if (json.name != name) {
color = '#f00'
}
const meta = document.createElement('div');
const content = document.createElement('div');
const hr = document.createElement('hr');
meta.innerHTML = '' + getdate() + ' ' + '' + json.name + '';
content.innerText = json.messages;
messages.appendChild(meta);
messages.appendChild(content);
messages.appendChild(hr);
window.scrollTo(0, document.body.scrollHeight);
});
socket.on('error', (error) => {
console.log(error)
})
</script>
然后用node或者bun运行,访问http://localhost:3000即可