Let's start by creating the Node.js server for our real-time chat application. We'll use Express.js as our web server framework and Socket.IO for WebSocket communication.
First, let's set up the server:
server.js
This server sets up a Socket.IO connection and handles events for user connections, messages, and disconnections. It also maintains a list of connected users.
Now, let's create the Angular frontend. First, we need to set up a new Angular project and install the necessary dependencies. You can do this by running the following commands:
ng new chat-app
cd chat-app
npm install socket.io-client
Next, let's create a chat service to handle the Socket.IO connection:
import { Injectable } from '@angular/core';
import { io, Socket } from 'socket.io-client';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private socket: Socket;
private messagesSubject = new BehaviorSubject<any[]>([]);
private usersSubject = new BehaviorSubject<string[]>([]);
constructor() {
this.socket = io('http://localhost:3000');
this.socket.on('newMessage', (message) => {
const currentMessages = this.messagesSubject.value;
this.messagesSubject.next([...currentMessages, message]);
});
this.socket.on('userList', (users) => {
this.usersSubject.next(users);
});
}
setUsername(username: string): void {
this.socket.emit('setUsername', username);
}
sendMessage(message: string): void {
this.socket.emit('sendMessage', message);
}
getMessages(): Observable<any[]> {
return this.messagesSubject.asObservable();
}
getUsers(): Observable<string[]> {
return this.usersSubject.asObservable();
}
}
Now, let's update the main component to use this service:
import { Component, OnInit } from '@angular/core';
import { ChatService } from './chat.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
username = '';
message = '';
messages: any[] = [];
users: string[] = [];
constructor(private chatService: ChatService) {}
ngOnInit() {
this.chatService.getMessages().subscribe(messages => {
this.messages = messages;
});
this.chatService.getUsers().subscribe(users => {
this.users = users;
});
}
setUsername() {
if (this.username.trim()) {
this.chatService.setUsername(this.username);
}
}
sendMessage() {
if (this.message.trim()) {
this.chatService.sendMessage(this.message);
this.message = '';
}
}
}
Finally, let's create the template for our chat application:
<div class="chat-container">
<div *ngIf="!username">
<h2>Enter your username</h2>
<input [(ngModel)]="username" placeholder="Username">
<button (click)="setUsername()">Join Chat</button>
</div>
<div *ngIf="username">
<h2>Welcome, {{ username }}!</h2>
<div class="chat-window">
<div class="messages">
<div *ngFor="let msg of messages">
<strong>{{ msg.user }}:</strong> {{ msg.message }}
</div>
</div>
<div class="users">
<h3>Online Users</h3>
<ul>
<li *ngFor="let user of users">{{ user }}</li>
</ul>
</div>
</div>
<div class="input-area">
<input [(ngModel)]="message" placeholder="Type a message" (keyup.enter)="sendMessage()">
<button (click)="sendMessage()">Send</button>
</div>
</div>
</div>
And add some basic styles:
.chat-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.chat-window {
display: flex;
height: 400px;
border: 1px solid #ccc;
margin-bottom: 20px;
}
.messages {
flex: 1;
overflow-y: auto;
padding: 10px;
}
.users {
width: 200px;
border-left: 1px solid #ccc;
padding: 10px;
overflow-y: auto;
}
.input-area {
display: flex;
}
.input-area input {
flex: 1;
padding: 5px;
}
.input-area button {
padding: 5px 10px;
}
To run the application, you'll need to start both the Node.js server and the Angular development server:
node server.js
to start the Node.js server.ng serve
to start the Angular development server.You can now access the chat application by opening a web browser and navigating to http://localhost:4200
. Open multiple browser windows to simulate different users joining the chat.
This implementation provides a basic real-time chat application using Angular and Node.js with Socket.IO. Users can join the chat by entering a username, send messages, and see other online users. The application updates in real-time as users join, leave, or send messages.
I'll guide you through implementing two-way encryption for messages in our chat application to enhance security. We'll use the AES (Advanced Encryption Standard) algorithm for encryption and decryption. This will ensure that messages are encrypted on the client-side before being sent to the server and decrypted only by the intended recipient.
Let's update our Angular and Node.js code step by step to include this encryption.
Let's start by updating our Angular application:
First, install the required dependency:
npm install crypto-js
Now, let's create an encryption service:
import { Injectable } from '@angular/core';
import * as CryptoJS from 'crypto-js';
@Injectable({
providedIn: 'root'
})
export class EncryptionService {
private key = 'your-secret-key'; // In a real application, this should be securely exchanged
encrypt(message: string): string {
return CryptoJS.AES.encrypt(message, this.key).toString();
}
decrypt(encryptedMessage: string): string {
const bytes = CryptoJS.AES.decrypt(encryptedMessage, this.key);
return bytes.toString(CryptoJS.enc.Utf8);
}
}
Next, let's update our chat service to use encryption:
import { Injectable } from '@angular/core';
import { io, Socket } from 'socket.io-client';
import { BehaviorSubject, Observable } from 'rxjs';
import { EncryptionService } from './encryption.service';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private socket: Socket;
private messagesSubject = new BehaviorSubject<any[]>([]);
private usersSubject = new BehaviorSubject<string[]>([]);
constructor(private encryptionService: EncryptionService) {
this.socket = io('http://localhost:3000');
this.socket.on('newMessage', (encryptedMessage) => {
const decryptedMessage = this.encryptionService.decrypt(encryptedMessage.message);
const message = { user: encryptedMessage.user, message: decryptedMessage };
const currentMessages = this.messagesSubject.value;
this.messagesSubject.next([...currentMessages, message]);
});
this.socket.on('userList', (users) => {
this.usersSubject.next(users);
});
}
setUsername(username: string): void {
this.socket.emit('setUsername', username);
}
sendMessage(message: string): void {
const encryptedMessage = this.encryptionService.encrypt(message);
this.socket.emit('sendMessage', encryptedMessage);
}
getMessages(): Observable<any[]> {
return this.messagesSubject.asObservable();
}
getUsers(): Observable<string[]> {
return this.usersSubject.asObservable();
}
}
Now, let's update the Node.js server to handle encrypted messages:
First, install the required dependency:
npm install crypto
Now, update the server code:
server.js
Now, let's break down the steps of how the encryption works in this system:
When a user sends a message:
EncryptionService
.When the server receives an encrypted message:
When a client receives a message:
ChatService
decrypts the message using the EncryptionService
.This implementation provides end-to-end encryption for the messages. The server can see the decrypted messages (which is often necessary for moderation or compliance reasons), but any intercepted messages between the client and server will be encrypted.
Remember, in a production environment:
This example demonstrates the concept of two-way encryption in a chat application. For a production application, you would need to implement more robust security measures and follow best practices for key management and secure communication.
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { io, Socket } from 'socket.io-client';
@Injectable({ providedIn: 'root' }) export class ChatService { private apiUrl = 'http://localhost:3000/api'; private socket: Socket;
constructor(private http: HttpClient) { this.socket = io('http://localhost:3000'); }
createUser(username: string): Observable<any> {
return this.http.post(${this.apiUrl}/users
, { username });
}
getRooms(): Observable<any[]> {
return this.http.get<any[]>(${this.apiUrl}/rooms
);
}
createRoom(name: string): Observable<any> {
return this.http.post(${this.apiUrl}/rooms
, { name });
}
getMessages(roomId: number): Observable<any[]> {
return this.http.get<any[]>(${this.apiUrl}/messages/${roomId}
);
}
joinRoom(roomId: number) { this.socket.emit('join room', roomId); }
leaveRoom(roomId: number) { this.socket.emit('leave room', roomId); }
sendMessage(userId: number, roomId: number, message: string) { this.socket.emit('chat message', { userId, roomId, message }); }
onNewMessage(): Observable<any> { return new Observable(observer => { this.socket.on('new message', (message) => { observer.next(message); }); }); } }
this service code use two
No Output
Run the code to generate an output.