I'm currently learning Node.js. To practice, I've decided to create a login server. The program goes as follows:
- User connects to local website (10.0.0.79, props to this users answer for helping me figure out how to set it up)
- User is presented with a login screen, with fields username and password.
- User enters the username and password, and the server checks if there are any matches, reading from a
JSON
file,creds.json
.
This is the file layout:
NodeServer
|-node_modules
|-(packages installed with node)
|-creds.json
|-index.html
|-index.js
|-log.txt
|-package-lock.json
|-package.json
There are a few areas I would like feedback on:
- SECURITY: Is my website secure in any way, shape, or form? I'm wondering if I could implement any security measures other than the ones that are built in to the methods provided by
Node.js
. Also, I know the passwords are plainly obvious to guess, but they are like that to ensure logging in as different users works. - EFFICIENCY: Is how I'm checking usernames and password efficient? Is there any better way to do this?
- BUILDING: Is how I loaded my website acceptable? Reading from a file and then ending the response?
- ASYNC/SYNC: I know I preform
async
andsync
calls at the same time. Is there any problem to this? - LOGGING: I log all connections to the server, and all login attempts. Is this a good practice, or am I overdoing what logging is supposed to accomplish?
Any and all feedback is appreciated and considered!
index.js
/* NODE START */
const http = require('http');
const fs = require('fs');
const url = require('url');
const port = 80;
var logFile = "log.txt";
const server = http.createServer(function(request, response) {
if(request.method = 'POST') {
let body = '';
request.on('data', chunk => {
body += chunk.toString();
});
request.on('end', () => {
//parse data
var credentials = body.split('&');
//Use below conditional in case there is an empty login attempt, or
//there is a page reload that contains no data
if(!(credentials[0] === '')) {
var username = credentials[0].substring(9);
var password = credentials[1].substring(9);
console.log(username + " " + password);
login(username, password, request);
}
});
}
//LOADING WEBPAGE
response.writeHead(200, { 'Content-Type': 'text/html' });
fs.readFile('index.html', function(error, data) {
if(error) {
response.writeHead(404);
response.write("Error: File Not Found");
} else {
response.write(data);
}
response.end();
});
//LOGGING
var address = request.socket.remoteAddress;
var logData = "[*] CONNECTION \n";
logData += "\t[+] FROM - " + address + "\n";
logData += "\t[+] DATE - " + getDate() + "\n";
logData += "\t[+] TIME - " + getTime() + "\n";
if(!(request.url === '/favicon.ico')) {
fs.appendFileSync(logFile, logData);
}
});
server.listen(port, '0.0.0.0');
console.log("Server is listening on port " + port);
function getDate() {
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
var day = date.getDate();
day = (day < 10 ? "0" : "") + day;
return month + "." + day + "." + year;
}
function getTime() {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
var sec = date.getSeconds();
sec = (sec < 10 ? "0" : "") + sec;
return hour + ":" + min + "." + sec;
}
function login(username, password, request) {
let rawdata = fs.readFileSync('creds.json');
let creds = JSON.parse(rawdata);
let users = ['ben', 'hannah', 'kristen', 'tony', 'katherine'];
for(var i = 0; i < users.length; i++) {
var person = creds[users[i]];
if(person['username'] === username && person['password'] === password) {
console.log("User [" + username + "] logged in!");
//LOG USER LOGIN
var userLoginData = "[*] LOGIN \n";
var loginAddress = request.socket.remoteAddress;
userLoginData += "\t[+] USER - " + username + "\n";
userLoginData += "\t[+] FROM - " + loginAddress + "\n";
userLoginData += "\t[+] DATE - " + getDate() + "\n";
userLoginData += "\t[+] TIME - " + getTime() + "\n";
fs.appendFileSync(logFile, userLoginData);
break;
}
}
}
/* NODE END */
/*
STATUS CODES
2xx: Success
- 200: OK
- 201: Created
- 204: No Content
- 202: Accepted
3xx: Redirection
- 304: Not Modified
- 301: Moved Permanently
4xx: Client Error
- 404: Not Found
- 401: Unauthorized
- 400: Bad Request
- 403: Forbidden
- 409: Conflict
*/
index.html
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Login Portal</title>
<style type="text/css">
input[type="text"], input[type="password"] {
border-radius: 10px;
width: 230px;
height: 35px;
font-size: 30px;
margin: 5px;
}
input[type="submit"] {
border-radius: 10px;
width: 100px;
height: 50px;
font-size: 20px;
}
label { font-size: 30px; }
#centered { text-align: center; margin-top: 200px; }
</style>
</head>
<body bgcolor="pink">
<div id="centered">
<h1>Login Portal</h1>
<form method="post" action="/">
<label>Username:</label>
<input type="text" name="username"><br>
<label>Password:</label>
<input type="password" name="password"><br>
<input type="submit">
</form>
</div>
</body>
</html>
creds.json
{
"ben": {
"username": "benus123",
"password": "benpw123"
},
"hannah": {
"username": "hannahus123",
"password": "hannahpw123"
},
"kristen": {
"username": "kristenus123",
"password": "kristenpw123"
},
"tony": {
"username": "tonyus123",
"password": "tonypw123"
},
"katherine": {
"username": "katherineus123",
"password": "katherinepw123"
}
}
Excerpt from the log file
[*] CONNECTION
[+] FROM - 10.0.0.79
[+] DATE - 06.29.2019
[+] TIME - 22:54.38
[*] LOGIN
[+] USER - benus123
[+] FROM - 10.0.0.79
[+] DATE - 06.29.2019
[+] TIME - 22:54.38