2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Node.jsでログインサーバーを作る - 2

Posted at

初めに

今回は、前回のログインサーバーを改造します(?)

前回とちがうところ

前回は一つのユーザーまでしか認証ができませんでしたが、今回はユーザーデータをjson形式で管理して複数のユーザーの認証ができるようにします

ファイル構成

今回のファイル構成は以下の通りです。

---|--public |
             |--main.html
             |--style.css
             |--main.js
    

   |--Server.js
   |--userdata.json
   

準備

まず、以下のコマンドをcmdで実行して、ログインサーバーのフォルダーに移動ください

cd C:\Users\<Your_Username>\Downloads\<Your_Project_FolderName>

※仮のpathです。実行するときはC:~の部分を作成したフォルダのpathに変更してください

次に、以下のコマンドを入力します

npm install express cors fs

※node.jsをインストールしていない方は、こちらからnode.jsをダウンロードしてください。

コピペ

以下のコードをコピペしましょう
サーバー側のjavascript

Server.js
const express = require('express');
const cors = require('cors');
const fs = require('fs');
const path = require('path');

const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.use(cors());
app.use(express.json());

app.post('/login', (req, res) => {
    const name = req.body.User;
    const pass = req.body.Password;

    if (!name || !pass) {
        return res.status(400).json({ error: 'ユーザー名またはパスワードが不足しています。' });
    }

    try {
        const userdata = fs.readFileSync('Userdata.json', 'utf-8');
        const ParseData = JSON.parse(userdata);

        const Fdata = ParseData.find(Udata => Udata.username === name && Udata.Password === pass);

        if (Fdata) {
            console.log('認証成功:', Fdata);
            res.json(Fdata);
        } else {
            res.status(401).json({ error: '認証に失敗しました。ユーザー名またはパスワードが正しくありません。' });
        }
    } catch (error) {
        console.error('エラーが発生しました:', error.message);
        res.status(500).json({ error: 'サーバーエラーが発生しました。' });
    }
});
app.post('/signup', (req, res) => {
    const name = req.body.User;
    const pass = req.body.Pass;
    const age = req.body.age;

    if (!name || !pass || !age) {
        return res.status(400).json({ error: 'ユーザー名またはパスワードまたは年齢等の情報が不足しています。' });
    }

    try {
        const Fdata = fs.readFileSync('Userdata.json', 'utf8');
        const ParseData = JSON.parse(Fdata);

        if (ParseData.find(Users => Users.username === name)) {
            return res.status(409).json({ error: "既に同じユーザー名が存在しています" });
        }

        // 新しいユーザー情報の作成
        const NewUserConfig = {
            username: name,
            Password: pass,
            age: age
        };

        // ユーザーデータに追加して保存
        ParseData.push(NewUserConfig);
        fs.writeFileSync('Userdata.json', JSON.stringify(ParseData, null, 2), 'utf8');

        res.json({ message: "サインアップが完了しました。" });
    } catch (error) {
        console.error('エラーが発生しました:', error.message);
        res.status(500).json({ error: 'サーバーエラーが発生しました。' });
    }
});

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'main.html'));
});

app.listen(3000, () => {
    console.log('server running on port 3000.');
});

html

main.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="load.css">
  <link rel="stylesheet" href="style.css">
  <title>ログイン</title>
 
</head>
<body>
<div id="Domcontainer"></div>
  <script src="script.js"></script>
</body>
</html>

クライアント側のjs

script.js
function afterAddEvent(EType) {
    switch(EType) {
        case "login":
            document.getElementById("loginForm").addEventListener("submit", function(event) {
                event.preventDefault();
                fetch('/login', {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json"
                    }, 
                    body: JSON.stringify({
                        User: document.getElementById('email').value,
                        Password: document.getElementById('password').value
                                        })
                })
                .then(response => response.json())
                .then(data => {
                    if (data.error) {
                        ChangeHTML('error'); 
                        setTimeout(() => {
                            document.getElementById('ErrorContent').textContent = data.error;
                        }, 500);
                        return;
                    }
                    ChangeHTML('Home');
                    setTimeout(() => {
                        document.getElementById('Main-Content').textContent = `Welcome back ${data.username}`;
                        document.getElementById('HomeMain').innerHTML = `
                        <p>mailaddress: ${data.username}</p>
                        <p>age: ${data.age}</p>`;
                    }, 500);
                })
                .catch(error => {
                    console.error("Error:", error);
                    ChangeHTML('error');
                    setTimeout(() => {
                        document.getElementById('ErrorContent').textContent = "FetchError: サーバーとの通信に失敗しました。";
                    }, 500);
                });
            });

            document.getElementById("passShow").addEventListener("change", function() {
                const passwordInput = document.getElementById("password");
                passwordInput.type = this.checked ? "text" : "password";
            });
            break;
            case "signup":
                document.getElementById("signupForm").addEventListener("submit", function(event) {
                    event.preventDefault(); // デフォルトのフォーム送信を防ぐ
                    // サインアップのデータ送信
                    
                    fetch('/signup', {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json"
                        }, 
                        body: JSON.stringify({
                            User: document.getElementById('email').value,
                            Pass: document.getElementById('password').value,
                            age: document.getElementById('age').value
                        })
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.error) {
                            ChangeHTML('error');
                            setTimeout(() => {
                                document.getElementById('ErrorContent').textContent = data.error;
                            }, 500);
                            return;
                        }
                        // サインアップ成功時の処理
                        ChangeHTML('login');
                        setTimeout(() => {
                            document.getElementById('Main-Content').textContent = "アカウント作成が完了しました。ログインしてください。";
                        }, 500);
                    })
                    .catch(error => {
                        console.error("Error:", error);
                        ChangeHTML('error');
                        setTimeout(() => {
                            document.getElementById('ErrorContent').textContent = "FetchError: サーバーとの通信に失敗しました。";
                        }, 500);
                    });
                });
                break;
        // 他のケース...
    }
}

window.onload = ChangeHTML('login');


function ChangeHTML(HTMLtype) {
    let NewHTML = "";
    switch(HTMLtype) {
        case "login":
            NewHTML = `
               <div class="login-container">
                <h1>ログイン</h1>
                <form id="loginForm">
                    <input type="text" id="email" placeholder="メールアドレス" required>
                    <input type="password" id="password" placeholder="パスワード" required>
                    <br><input type="checkbox" id="passShow"> パスワードを表示
                        <button class="login-button" type="submit">次へ</button>
                </form>
                <p>アカウントをお持ちでないですか? <a href="#" onclick="ChangeHTML('signup')">作成する</a></p>
              </div>
            `;
            setTimeout(() => {
                afterAddEvent("login");
            }, 500);
            break;
            
        case "signup":
            NewHTML = `
              <div class="signup-container">
                <h1>サインアップ</h1>
                <form id="signupForm">
                <input type="text" id="email" placeholder="メールアドレス" required>
                    <input type="password" id="password" placeholder="パスワード" required>
                    <input type="number" id="age" placeholder="年齢を入力">
                        <button class="login-button" type="submit">次へ</button>
                </form>
                <p>既にアカウントをお持ちですか? <a href="#" onclick="ChangeHTML('login')">ログインする</a></p>
              </div>
            `;
            setTimeout(() => {
                afterAddEvent("signup");
            }, 500);
            break;

        case "error":
            NewHTML = `
              <div class="login-container">
                <h1>Error</h1>
                <p id="ErrorContent"></p>
              </div>`;
            break;

        case "Home":
            NewHTML = `
              <div class="login-container">
                <h1>Home</h1>
                <h1 id="Main-Content"></h1>
                <div id="HomeMain"></div>
              </div> 
            `;
            break;

        default:
            NewHTML = `
              <div class="error-container">
                <h1>Error</h1>
                <p>エラー:ページが存在しないよ!</p>
                <p>error: page is not found!</p>
              </div>
            `;
    }
    document.getElementById('Domcontainer').innerHTML = NewHTML;
}
window.onload = ChangeHTML('login');

css

style.css
body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f5f5f5;
  }
  .login-container {
    width: 360px;
    padding: 40px;
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    text-align: center;
  }
  .login-container img {
    width: 75px; 
    margin-bottom: 20px;
  }
  h1 {
    font-size: 24px;
    color: #202124; /* テキスト色 */
    margin: 0 0 20px;
  }
  p {
    font-size: 14px;
    color: #5f6368; /* 説明文の色 */
    margin: 0 0 20px;
  }
  input[type="email"],
  input[type="text"],
  input[type="password"],
  input[type="number"] {
    width: 100%;
    padding: 12px;
    margin: 8px 0;
    border: 1px solid #ddd;
    border-radius: 4px;
    box-sizing: border-box;
  }
  .button-container {
    margin-top: 20px;
  }
  .login-button {
    width: 100%;
    padding: 10px;
    background-color: #0078d4;
    color: #fff;
    border: none;
    border-radius: 4px;
    font-size: 16px;
    cursor: pointer;
  }
  .login-button:hover {
    background-color: #005ea1; /* ホバー時の色 */
  }
  .forgot-email,
  .create-account {
    font-size: 14px;
    color: #1a73e8;
    text-decoration: none;
    display: inline-block;
    margin-top: 20px;
  }
  .forgot-email:hover,
  .create-account:hover {
    text-decoration: underline;
  }
  .error-message {
    color: red;
    margin-top: 15px;
    font-size: 14px;
  }

json(確認したら自動的に生成されませんでした)

Userdata.json
[

]

説明(?)

今回はfsを使って、複数ユーザーのログインを実装しています
ちなみに、Userdata.jsonを削除した状態でやると、サーバーでエラーが起きます

最後に

いかがだったでしょうか?今回はfsとexpressを使って、ログイン機能を作りました。ちなみに、今回もsignupの処理がうまくいかなかったので、ChagtGPTに修正してもらいました。
それではまたお会いしましょう!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?