Jump to content

Server-Side Scripting/Cookies and Sessions/Node.js (Express)

From Wikiversity

app.js

[edit | edit source]
// Demonstrates a complete server-side website using:
//   * static HTML and CSS
//   * a template
//   * a code module
//
// NOTE: Static pages (html, css, images, etc.) are placed in
// a folder named "static". Template pages are placed in a folder
// named "templates".
//
// Folder structure:
// app.js
// hello.js
// static
//   index.html
//   static.html
//   styles.css
// templates
//   template.html
//
// References:
//  https://repl.it/languages/express
//  https://expressjs.com/en/guide/routing.html
//  https://www.npmjs.com/package/express-fileupload
//  https://www.tutorialspoint.com/expressjs/expressjs_cookies.htm
//  https://www.geeksforgeeks.org/session-cookies-in-nodejs/
//  https://www.geeksforgeeks.org/node-js-crypto-randombytes-method/

const express = require("express");
const fileUpload = require('express-fileupload');
const cookieParser = require("cookie-parser");
const session = require("express-session");
const crypto = require("crypto");

const app = express();

app.use(express.static(__dirname + '/static'));
app.use(express.urlencoded({
        extended: true
}));

app.use(fileUpload({
    limits: { fileSize: 1 * 1024 * 1024 },
}));
app.use(cookieParser());
app.use(session({
    resave: false,
    saveUninitialized: false,
    secret: crypto.randomBytes(16).toString("hex")
}));

const fs = require("fs");
fs.readdirSync("./routes").map((filename) => {
    const module = require("./routes/" + filename);
    const route = filename.replace(".js", "")
    app.use("/" + route, module);
});

app.listen(3000, () => console.log('server started'));

routes/lesson12.js

[edit | edit source]
// Demonstrates session and cookie processing. The username is stored
// as a cookie and an internal userid is saved in a session variable.
// Also demonstrates secure password authentication using bcrypt salt
// and hash.
//
// References:
//  https://en.wikibooks.org/wiki/JavaScript
//  https://www.geeksforgeeks.org/http-cookies-in-node-js/
//  https://www.geeksforgeeks.org/session-cookies-in-nodejs/
//  https://www.npmjs.com/package/bcrypt

const express = require("express");
const bcrypt = require("bcrypt");
const fs = require("fs");
const handlebars = require('handlebars');
const router = express.Router();

users = [
    // Password is the same as the username, just salted and hashed.
    // Don't do this in a production application! Use custom passwords.
    { "userid": 1, "username": "admin", 
        "password": "$2b$10$l20wKFNqyzWl9NgeexjQ9el9KY7HzbTAPefSyntaZE.jqJlHZI0Ba" },
    { "userid": 2, "username": "test", 
        "password": "$2b$10$T.7DuAdfGVzq8uP1.xYZLe8rbPrOE6/DtMqbT5.O/bYwTFMZDC6ru" }
]

router.get("/", function (request, response) {
    let username = request.cookies.username;
    let userid = request.session.userid;
    result = build_form(username, userid);
    response.send(result);
});

router.post("/", function (request, response) {
    if (request.body["reload"]) {
        response.redirect(request.originalUrl);
    }
    else if (request.body["log-out"]) {
        request.session.destroy();
        let username = request.cookies.username;
        let userid = null;
        result = build_form(username, userid);
        response.send(result);
    }
    else if (request.body["forget-me"]) {
        request.session.destroy();
        result = build_form(null, null);
        response.cookie("username", "", { expires: 0 });
        response.send(result);
    }
    else {
        let username = request.body.username;
        let password = request.body.password;
        let userid = authenticateUser(username, password);
        if (userid) {
            request.session.userid = userid;
            result = build_form(username, userid);
            response.cookie("username", username);
            response.send(result);    
        }
        else {
            response.redirect(303, request.originalUrl);
        }
    }
});

function build_form(username, userid) {
    let cookie = !!username;
    let session = !!userid;
    if (username && userid) {
        welcome = "Welcome back " + username + "! You are logged in.";
    }
    else if (username) {
        welcome = "Welcome back " + username + "! Please log in.";
    }
    else {
        welcome = "Welcome! Please log in.";
    }

    let source = fs.readFileSync("./templates/lesson12.html");
    let template = handlebars.compile(source.toString());
    let data = {
        cookie: cookie,
        session: session,
        welcome: welcome,
        username: username
    }
    result = template(data);
    return result
}

function authenticateUser(username, password) {
    for (let index = 0; index < users.length; index++) {
        let user = users[index];
        if (user.username == username) {
            if (bcrypt.compareSync(password, user.password)) {
                // Should track successful logins
                return user.userid;
            } else {
                // Should track failed attempts, lock account, etc.
                return null;
            }
        }        
    }
    return null;
}

function generateHashedPassword(password) {
    // Use this function to generate hashed passwords to save in 
    // the users list or a database.
    let salt = bcrypt.genSaltSync();
    let hashed = bcrypt.hashSync(password, salt);
    return hashed    
}    

module.exports = router;

templates/lesson12.html

[edit | edit source]
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Lesson 12</title>
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <h1>Cookies and Sessions</h1>
    <p>Cookie: {{cookie}}<br>Session: {{session}}</p>
    <p>{{welcome}}</p>
    <hr>
    <form method="POST">
        <p><label for="username">Username:</label>
            <input type="text" id="username" name="username" value="{{username}}">
        </p>
        <p><label for="password">Password:</label>
            <input type="password" id="password" name="password">
        </p>
        <input type="submit" id="log-in" name="log-in" value="Log In">&nbsp;
        <input type="submit" id="log-out" name="log-out" value="Log Out">&nbsp;
        <input type="submit" id="forget-me" name="forget-me" value="Forget Me">&nbsp;
        <input type="submit" id="reload" name="Reload" value="Reload">
    </form>
</body>

</html>

Try It

[edit | edit source]

See Server-Side Scripting/Routes and Templates/Node.js (Express) to create a test environment.

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy