Trong dự án này, chúng ta sẽ sử dụng giao thức WSS để thiết lập kết nối giữa frontend và backend mà không cần đến các chứng chỉ được xác thực. Thay vào đó, chúng ta sẽ tạo khóa riêng tư và chứng chỉ tự ký bằng OpenSSL:
Chúng tôi sẽ không đề cập chi tiết về quá trình kết nối WSS mà đi thẳng vào việc thực hiện.
1. Tạo khóa riêng tư và chứng chỉ:
Xem thêm tại đây: Hướng dẫn cài đặt và tạo chứng chỉ bằng OpenSSL - Nguồn sách
2. Dịch vụ phía server bằng Rust:
Đặt các file server.crt và server.key đã tạo vào thư mục d:\\User\\Desktop\\wss\\openssl.
Dựa trên các gói phụ thuộc sau:
[dependencies]
rustls = "0.19.0"
tokio-rustls = "0.22.0"
tokio = { version = "1", features = ["full"] }
tokio-tungstenite = "0.20"
futures-util = "0.3"
Mã Rust:
use futures_util::sink::SinkExt;
use futures_util::stream::{Stream, StreamExt};
use rustls::ServerConfig;
use std::fs::File;
use std::io::BufReader;
use std::sync::Arc;
use tokio::net::{TcpListener, TcpStream};
use tokio_rustls::TlsAcceptor;
use tokio_tungstenite::accept_async;
use tokio_tungstenite::tungstenite::protocol::Message;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let certs = rustls::internal::pemfile::certs(&mut BufReader::new(File::open(
"d:\\User\\Desktop\\wss\\openssl\\server.crt",
)?))?;
let key = rustls::internal::pemfile::pkcs8_private_keys(&mut BufReader::new(File::open(
"d:\\User\\Desktop\\wss\\openssl\\server.key",
)?))?[0].clone();
let tls_cfg = {
let mut cfg = ServerConfig::new(rustls::NoClientAuth::new());
cfg.set_single_cert(certs, key)?;
Arc::new(cfg)
};
let tls_acceptor = TlsAcceptor::from(tls_cfg);
let addr = "127.0.0.1:10096";
let listener = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
while let Ok((stream, _)) = listener.accept().await {
let acceptor = tls_acceptor.clone();
tokio::spawn(async move {
if let Ok(tls_stream) = acceptor.accept(stream).await {
let websocket_result = accept_async(tls_stream).await;
match websocket_result {
Ok(mut ws_stream) => {
println!("WebSocket connection established");
while let Some(message_result) = ws_stream.next().await {
match message_result {
Ok(message) => {
if message.is_text() || message.is_binary() {
println!("Received message: {}", message);
if let Err(_) = ws_stream.send(message).await {
break;
}
}
}
Err(e) => {
println!("Error: {}", e);
break;
}
}
}
}
Err(e) => {
println!("Error during the websocket handshake occurred: {}", e);
}
}
}
});
}
Ok(())
}
3. Client bằng Angular:
Cấu hình Angular:
Đặt các file client.crt và client.key vào cùng cấp thư mục với file package.json.
Nội dung package.json:
"scripts": {
"start": "ng serve --host 0.0.0.0 --port 443 --ssl true --ssl-cert ./client.crt --ssl-key ./client.key",
}
Mã Angular:
import { webSocket } from 'rxjs/webSocket';
ngOnInit() {
this.websocketTest();
}
websocketTest() {
const url: string = 'wss://127.0.0.1:10096';
const myWebSocket = webSocket({
url: url,
openObserver: {
next: () => {
console.info('WebSocket connection established: ' + url);
},
error: (err) => {
console.error('WebSocket connection error: ' + url);
console.error(err);
},
},
});
const data = JSON.stringify({ name: 'John Doe', age: 25, gender: 'Male' });
myWebSocket.next(data);
console.log('Client sent request: ', data);
myWebSocket.subscribe(
next => {
console.log('Client received response: ', next);
},
error => {
console.error('WebSocket error: ' + url);
console.error(error);
}
);
}
4. Cài đặt Google Chrome:
Nhấp chuột phải vào biểu tượng Google Chrome > Thuộc tính > Phím tắt > Mục tiêu (thêm tham số):
Từ: "C:\Program Files\Google\Chrome\Application\chrome.exe"
Thành: "C:\Program Files\Google\Chrome\Application\chrome.exe" --ignore-certificate-errors
Tham số này sẽ bỏ qua các lỗi liên quan đến chứng chỉ.