It implements a login function that authenticates users compared to the value of the database.
When I run node red and enter id/pw for the first time, it works fine. Compare the values with DB to move on only when they match. However, I come back to the login screen and leave the input empty and just press the login button to move on to the next screen again. (As if I succeeded in logging in.) I wonder where the hell the problem is.
I think it's a problem with the global variable that you set as the input not being initialized, or there's an error in the logic itself.
Please help me.
[
{
"id": "75ce2ad0555f4266",
"type": "http in",
"z": "b1537c574e27a2f9",
"name": "",
"url": "/login_action",
"method": "post",
"upload": false,
"swaggerDoc": "",
"x": 210,
"y": 580,
"wires": [
[
"ad388a18420d9f62"
]
]
},
{
"id": "ad388a18420d9f62",
"type": "function",
"z": "b1537c574e27a2f9",
"name": "์
๋ ฅํ value์ ๋ํด set global",
"func": "if (msg.payload.userID != \"\" && msg.payload.password != \"\") {\n global.set(\"loginUserID\", msg.payload.userID);\n global.set(\"loginPassword\", msg.payload.password);\n //global.set(\"msg_login_action\",msg);\n} \nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 580,
"wires": [
[
"0a3dc9fe4f6967a6"
]
]
},
{
"id": "0a3dc9fe4f6967a6",
"type": "function",
"z": "b1537c574e27a2f9",
"name": "์
๋ ฅํ Username์ด mySQL์ ์กด์ฌํ๋์ง ํ์ธ",
"func": "var id = global.get(\"loginUserID\");\nvar password = global.get(\"loginPassword\");\nmsg.topic = \"SELECT * FROM users WHERE userID = ?\";\nif (id && password) {\n msg.payload = [id];\n} else {\n // ID๋ Password๊ฐ ์๋ ๊ฒฝ์ฐ, ๋น ๋ฐฐ์ด ๋ฐํ\n msg.payload = [];\n}\n//msg.topic = \"SELECT * FROM users WHERE userName = ? AND password = ?\";\n//msg.payload = [id];\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 780,
"y": 580,
"wires": [
[
"442a018c69b061ef"
]
]
},
{
"id": "442a018c69b061ef",
"type": "mysql",
"z": "b1537c574e27a2f9",
"mydb": "23139c6750c1e4b8",
"name": "",
"x": 290,
"y": 640,
"wires": [
[
"45720baf77e5d803"
]
]
},
{
"id": "45720baf77e5d803",
"type": "function",
"z": "b1537c574e27a2f9",
"name": "Authentication",
"func": "/*if(msg.payload!=null){\n msg.payload=\"Login Success\";\n}else {\n msg.payload =\"Login Failed\";\n}\nreturn msg;*/\n// ์ฌ์ฉ์๋ฅผ ์ธ์ฆํ๋ ํจ์\nvar loginUserID = global.get(\"loginUserID\");\nvar loginPassword = global.get(\"loginPassword\");\n\n\nif (msg.payload.length > 0) {\n var userID = msg.payload[0].userID;\n var userPassword = msg.payload[0].password;\n if (userPassword === loginPassword) { // ์
๋ ฅ๋ ๋น๋ฐ๋ฒํธ์ ๋น๊ต\n\n var encodedUserID = Buffer.from(userID).toString('base64');\n msg.cookies = {\n COOKIE: {\n value: encodedUserID,\n maxAge: 900000 // ์ฟ ํค ์ ํจ ์๊ฐ (๋ฐ๋ฆฌ์ด), ์ฌ๊ธฐ์๋ 15๋ถ\n }\n };\n msg.redirect = \"http://localhost:1880/ui\"; // ๋ก๊ทธ์ธ ์ฑ๊ณต ์ ๋์๋ณด๋๋ก ๋ฆฌ๋ค์ด๋ ํธ\n } else {\n msg.payload = \"2\";\n }\n} else {\n msg.payload = \"1\";\n}\n\n\nreturn msg;\n\n\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 440,
"y": 640,
"wires": [
[
"91d7e94b135bbb57"
]
]
},
{
"id": "91d7e94b135bbb57",
"type": "switch",
"z": "b1537c574e27a2f9",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "else"
},
{
"t": "eq",
"v": "1",
"vt": "str"
},
{
"t": "eq",
"v": "2",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 590,
"y": 640,
"wires": [
[
"1021190647257c4d"
],
[
"ddbd12536354d9fa"
],
[
"2aaf8130381ccb06"
]
]
},
{
"id": "ddbd12536354d9fa",
"type": "function",
"z": "b1537c574e27a2f9",
"name": "= 1 : Unknown User",
"func": "msg.payload = \"Login Failed: User Not Found.\";\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 770,
"y": 660,
"wires": [
[
"665ed3a23ab05c5f"
]
]
},
{
"id": "2aaf8130381ccb06",
"type": "function",
"z": "b1537c574e27a2f9",
"name": "= 2 : Wrong Password",
"func": "msg.payload = \"Login Failed: Invalid Password.\";\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 760,
"y": 700,
"wires": [
[
"665ed3a23ab05c5f"
]
]
},
{
"id": "665ed3a23ab05c5f",
"type": "function",
"z": "b1537c574e27a2f9",
"name": "Login Failed",
"func": "var msg1 = msg.payload;\nvar msg=global.get(\"msg_login_action\") || \"\";\nmsg.payload = msg1;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 950,
"y": 680,
"wires": [
[
"f06841e5dc3d9282"
]
]
},
{
"id": "f06841e5dc3d9282",
"type": "template",
"z": "b1537c574e27a2f9",
"name": "page",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "<script>\n // ์น ํ์ด์ง๊ฐ ๋ก๋๋ ๋ ์คํ๋๋ ํจ์\n window.onload = function() {\n // ์๋ฒ์์ ์ ๋ฌ๋ฐ์ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์ด\n var message = \"{{payload}}\"; // ์ด ๋ถ๋ถ์ Node-RED์์ ์ ๋ฌํ ๋ฉ์์ง๋ฅผ ๋ฃ์ด์ผ ํจ\n\n // ๋ก๊ทธ์ธ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ํ์
์ฐฝ์ ํ์\n if (message.includes(\"Login Failed\")) {\n // ๋ก๊ทธ์ธ ์คํจ ์ ํ์
์ฐฝ ํ์\n alert(message);\n \n // ํ์
ํ์ธ ํ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์๋ ์ด๋\n window.location.href = \"http://192.168.0.18:1880/login\"; // ๋ก๊ทธ์ธ ํ์ด์ง URL๋ก ๋ณ๊ฒฝํด์ผ ํจ\n }\n };\n</script>\n\n",
"output": "str",
"x": 1090,
"y": 680,
"wires": [
[
"08750f2d966af0ce"
]
]
},
{
"id": "1021190647257c4d",
"type": "template",
"z": "b1537c574e27a2f9",
"name": "page",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "<script>\nwindow.location.href = \"http://192.168.0.18:1880/ui\";\n</script>",
"output": "str",
"x": 950,
"y": 640,
"wires": [
[
"50ef68fa45d8e864",
"c913d0c7d0a84945"
]
]
},
{
"id": "50ef68fa45d8e864",
"type": "http response",
"z": "b1537c574e27a2f9",
"name": "Go to Dashboard",
"statusCode": "",
"headers": {},
"x": 1130,
"y": 620,
"wires": []
},
{
"id": "08750f2d966af0ce",
"type": "http response",
"z": "b1537c574e27a2f9",
"name": "Return to Login",
"statusCode": "",
"headers": {},
"x": 1240,
"y": 680,
"wires": []
},
{
"id": "7037a375ba2d0cc2",
"type": "http in",
"z": "b1537c574e27a2f9",
"name": "",
"url": "/login",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 180,
"y": 540,
"wires": [
[
"39dd5592efadfa8d"
]
]
},
{
"id": "39dd5592efadfa8d",
"type": "template",
"z": "b1537c574e27a2f9",
"name": "<style>",
"field": "payload.style",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "html {\n display: flex;\n justify-content: center;\n align-items: center;\n font-size: 150%;\n height: 70vh; /* ๋ณด๋ ์ฌ๋์ ํ์ด์ง์ ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋จ. */\n}\n\nbody {\n font-size: 14px;\n font-family: 'Roboto', sans-serif;\n background-color: #023047;\n}\n\n.logo-wrapper {\n text-align: center;\n margin-bottom: 20px;\n}\n\n.logo {\n width: 200px; /* ๋ก๊ณ ์ด๋ฏธ์ง์ ๋๋น๋ฅผ ์กฐ์ */\n display: inline-block; /* ๋ก๊ณ ๋ฅผ ๊ฐ๋ก ์ค์ ์ ๋ ฌํ๊ธฐ ์ํด inline-block ์์ฑ ์ ์ฉ */\n\n}\n.logo img {\n width: 100%; /* ๋ก๊ณ ์ด๋ฏธ์ง์ ๋๋น๋ฅผ ๋ถ๋ชจ ์์์ ๋ง๊ฒ ์กฐ์ */\n height: auto; /* ์ด๋ฏธ์ง ๋น์จ ์ ์ง */\n}\n\n.login-wrapper {\n text-align: center; /* ๋ถ๋ชจ ์์์ ๋ํด ๊ฐ์ด๋ฐ ์ ๋ ฌ์ ์ ์ฉ */\n margin-bottom: 20px;\n width: 400px;\n padding: 40px;\n box-sizing: border-box;\n background-color: #fff; /* ํฐ ๋ฐฐ๊ฒฝ ์ถ๊ฐ */\n border-radius: 10px; /* ๋ชจ์๋ฆฌ๋ฅผ ๋ฅ๊ธ๊ฒ ๋ง๋ฆ */\n box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.1); /* ๊ทธ๋ฆผ์ ํจ๊ณผ ์ถ๊ฐ */\n display: flex; /* ์์ ์์๋ฅผ ๊ฐ๋ก๋ก ๋ฐฐ์นํ๊ธฐ ์ํด flex ์์ฑ ์ ์ฉ */\n flex-direction: column; /* ์์ ์์๋ฅผ ์ธ๋ก๋ก ๋ฐฐ์น */\n align-items: center; /* ์์ ์์๋ฅผ ๊ฐ์ด๋ฐ ์ ๋ ฌ */\n}\n\n#login-form {\n width: 100%; /* ํผ์ ๋๋น๋ฅผ 100%๋ก ์ค์ */\n margin-bottom: 20px; /* ํ๋จ ์ฌ๋ฐฑ ์ถ๊ฐ */\n}\n#login-form > input {\n width: 100%;\n height: 48px;\n padding: 0 10px;\n box-sizing: border-box;\n margin-bottom: 10px;\n border-radius: 6px;\n background-color: #F8F8F8;\n border: 2px solid #023047; /* ๋ชจ๋ ํ
๋๋ฆฌ์ ๋ํ ์์ ์ค์ */\n font-family: 'Lucida Sans', sans-serif; /* ์ํ๋ ํฐํธ๋ก ๋ณ๊ฒฝ */\n\n}\n\n#login-form > input::placeholder {\n color: #D2D2D2;\n}\n\n#login-form > input[type=\"submit\"] {\n color: #fff;\n font-size: 16px;\n background-color: #FFB703;\n margin-top: 20px;\n font-family: 'Lucida Sans', sans-serif; /* ์ํ๋ ํฐํธ๋ก ๋ณ๊ฒฝ */\n border: none; /* ํ
๋๋ฆฌ ์ ๊ฑฐ */\n width: 100%; /* ๋ฒํผ์ ๋๋น๋ฅผ 100%๋ก ์ค์ ํ์ฌ ํผ๊ณผ ๋์ผํ ๋๋น๋ฅผ ๊ฐ์ง๋๋ก ํจ */\n}\n\n.submit-btn {\n color: #fff; \n font-size: 16px;\n margin-top: 2px;\n background-color: #FFB703; \n border: 2px solid #FFB703; /* ํฉ์ ํ
๋๋ฆฌ */\n border-radius: 6px; /* ๋ชจ์๋ฆฌ๋ฅผ ๋ฅ๊ธ๊ฒ ๋ง๋ฆ */\n //padding: 12px 0; /* ์์๋ 12px, ์ข์ฐ 0 */\n width: 100%; /* ๋ฒํผ์ ๋๋น๋ฅผ 100%๋ก ์ค์ ํ์ฌ ํผ๊ณผ ๋์ผํ ๋๋น๋ฅผ ๊ฐ์ง๋๋ก ํจ */\n height: 48px;\n cursor: pointer; /* ์ปค์ ๋ชจ์์ ํฌ์ธํฐ๋ก ๋ณ๊ฒฝ */\n font-family: 'Lucida Sans', sans-serif; /* ์ํ๋ ํฐํธ๋ก ๋ณ๊ฒฝ */\n}\n\n.submit-btn:hover {\n background-color: #ffa500; /* ํธ๋ฒ ์ ๋ฐฐ๊ฒฝ์ ๋ณ๊ฒฝ */\n}\n\n#login-form > input[type=\"checkbox\"] {\n display: none;\n}\n\n#login-form > label {\n color: #999999;\n}\n\n#login-form input[type=\"checkbox\"] + label {\n cursor: pointer;\n padding-left: 26px;\n background-image: url(\"checkbox.png\");\n background-repeat: no-repeat;\n background-size: contain;\n font-family: 'Lucida Sans', sans-serif; /* ์ํ๋ ํฐํธ๋ก ๋ณ๊ฒฝ */\n\n}\n\n#login-form input[type=\"checkbox\"]:checked + label {\n background-image: url(\"checkbox-active.png\");\n background-repeat: no-repeat;\n background-size: contain;\n font-family: 'Lucida Sans', sans-serif; /* ์ํ๋ ํฐํธ๋ก ๋ณ๊ฒฝ */\n}\n/* ###### 5. direction ###### */\n.direction__container {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n}\n.direction__container p {\n text-align: center;\n margin-top: 10px;\n}",
"output": "str",
"x": 560,
"y": 540,
"wires": [
[
"ae97fec1521bf021"
]
]
},
{
"id": "ae97fec1521bf021",
"type": "template",
"z": "b1537c574e27a2f9",
"name": "",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "<!DOCTYPE html>\n<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<style> {{{payload.style}}} </style>\n</head>\n<body>\n <div class=\"login-wrapper\">\n <div class=\"logo-wrapper\">\n <div class=\"logo\">\n <img src=\"http://theconsol.co.kr/public/img/logo/logo.png\">\n </div>\n </div>\n <form method=\"post\" action=\"http://192.168.0.18:1880/login_action\" id=\"login-form\">\n <input type=\"text\" name=\"userID\" placeholder=\"ID\">\n <input type=\"password\" name=\"password\" placeholder=\"Password\">\n <label for=\"remember-check\">\n <input type=\"checkbox\" id=\"remember-check\">์์ด๋ ์ ์ฅํ๊ธฐ\n </label>\n <input type=\"submit\" id=\"login-button\" value=\"Login\">\n </form>\n <button class=\"submit-btn\" onclick=\"goToSignUpPage()\">Sign up</button> \n </div>\n<script>\n document.addEventListener(\"DOMContentLoaded\", function() {\n console.log(\"JavaScript ์ฝ๋๊ฐ ๋ก๋๋์์ต๋๋ค.\");\n // ํผ ์ ์ถ ์ ์
๋ ฅ ํ๋๊ฐ ๋น์ด ์๋์ง ํ์ธํ๊ณ , ๋น์ด ์์ผ๋ฉด ์ ์ถ์ ๋ง์\n document.getElementById(\"login-form\").addEventListener(\"submit\", function(event) {\n if (useridInput.value.trim() === \"\" || passwordInput.value.trim() === \"\") {\n // ์
๋ ฅ ํ๋๊ฐ ๋น์ด ์์ผ๋ฉด ํผ ์ ์ถ์ ๋ง์\n event.preventDefault();\n // ์ฌ์ฉ์์๊ฒ ๋ฉ์์ง ํ์ (์๋ฅผ ๋ค์ด alert ์ฌ์ฉ)\n alert(\"ID์ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์.\");\n }\n });\n // Sign up ํ์ด์ง๋ก ์ด๋ํ๋ ํจ์\n function goToSignUpPage() {\n console.log(\"Sign up ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค.\");\n window.location.href = \"http://192.168.0.18:1880/signup\"; // \"/signup\"์ผ๋ก ๋ณ๊ฒฝ\n }\n \n // ํ์ ์
๋ ฅ ํ๋\n var useridInput = document.getElementById(\"userID\");\n var passwordInput = document.getElementById(\"password\");\n var loginButton = document.getElementById(\"login-button\");\n\n // ์
๋ ฅ ํ๋์ ๋ณ๊ฒฝ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ์ฌ ์ ์ถ ๋ฒํผ ํ์ฑํ ์ํ ๋ณ๊ฒฝ\n useridInput.addEventListener(\"input\", toggleSubmitButton);\n passwordInput.addEventListener(\"input\", toggleSubmitButton);\n\n function toggleSubmitButton() {\n // ์ฌ์ฉ์๋ช
๊ณผ ๋น๋ฐ๋ฒํธ๊ฐ ๋ชจ๋ ์ฑ์์ ธ ์์ ๋ ์ ์ถ ๋ฒํผ ํ์ฑํ\n if (useridInput.value.trim() !== \"\" && passwordInput.value.trim() !== \"\") {\n loginButton.disabled = false;\n } else {\n loginButton.disabled = true;\n }\n }\n\n\n });\n</script>\n</body>\n</html>\n",
"output": "str",
"x": 860,
"y": 540,
"wires": [
[
"98add455cdc50a57"
]
]
},
{
"id": "a05c6ac2e72411e4",
"type": "http in",
"z": "b1537c574e27a2f9",
"name": "HTTP Input",
"url": "/login_action",
"method": "post",
"upload": false,
"swaggerDoc": "",
"x": 190,
"y": 760,
"wires": [
[
"5671a69f69d959b8"
]
]
},
{
"id": "3ef1ab865351c4d2",
"type": "http response",
"z": "b1537c574e27a2f9",
"name": "HTTP Response",
"statusCode": "",
"headers": {},
"x": 590,
"y": 760,
"wires": []
},
{
"id": "5671a69f69d959b8",
"type": "function",
"z": "b1537c574e27a2f9",
"name": "Check Cookie",
"func": "var loginCookie = msg.req.cookies.COOKIE; // ์ฟ ํค ์ด๋ฆ์ด \"COOKIE\"์ธ ๊ฒฝ์ฐ\nif (loginCookie) {\n // ์ฟ ํค๋ฅผ ํ์ธํ์ฌ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ฒ๋ฆฌํ๋ ์ถ๊ฐ์ ์ธ ๋ก์ง ๊ตฌํ\n // ์ฌ๊ธฐ์๋ ์ฟ ํค๋ฅผ ํด์ํ์ฌ ๋ก๊ทธ์ธ ์ํ๋ฅผ ํ์ธํ๋ ๋ก์ง ๋ฑ์ด ๋ค์ด๊ฐ ์ ์์ต๋๋ค.\n\n // ์ด๋ฏธ ๋ก๊ทธ์ธํ ์ํ๋ผ๋ฉด ๋์๋ณด๋๋ก ๋ฆฌ๋ค์ด๋ ํธ\n return { payload: null, redirect: \"http://192.168.0.18/ui\" };\n} else {\n // ๋ก๊ทธ์ธ์ด ํ์ํ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ค\n return { payload: \"you have to login\" };\n}\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 360,
"y": 760,
"wires": [
[
"3ef1ab865351c4d2"
]
]
},
{
"id": "98add455cdc50a57",
"type": "http response",
"z": "b1537c574e27a2f9",
"name": "",
"statusCode": "",
"headers": {},
"x": 1070,
"y": 540,
"wires": []
},
{
"id": "c913d0c7d0a84945",
"type": "debug",
"z": "b1537c574e27a2f9",
"name": "debug 2",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1240,
"y": 560,
"wires": []
},
{
"id": "23139c6750c1e4b8",
"type": "MySQLdatabase",
"name": "",
"host": "127.0.0.1",
"port": "3306",
"db": "project",
"tz": "",
"charset": "UTF8"
}
]