الدرس الأول في الNode.js عمل تسجيل دخول
.....
بعد المقدمة عن باترن الـNode.js في المقال السابق سأقوم بشرح اهم الدروس التي لطالما كانت اولى الخطوات المتبعه في جميع اللغات لمعرفة كيفية التعامل مع:
- قواعد البيانات.
- طريقة ارسال المعلومات من Form.
- طريقة استقبال المعلومات المرسلة.
- وبشكل خاص في الـNode.js , كيفية التعامل مع البيانات من ومطابقتها مع قاعدة البيانات.
- التعامل مع الـCookies بعد تسجيل الدخول.
في بداية هذا الدرس, سأفترض امرين الأول هو مسبقا بأنك قمت بتثبيت الـ Dependencies وهم:
npm install mysql
npm install express
npm install cookie-parser
والثاني هو ان تكون لديك معرفة متوسطة مسبقة بلغة الـ javascript و jquery
وبعد التأكد من التثبيت, اعمل قاعدة بيانات سواء كانت خارجية ام داخليةوستكون كالتالي مثلا:
-- phpMyAdmin SQL Dump
-- version 4.5.1
-- http://www.phpmyadmin.net
--
-- Host: 127.0.0.1
-- Generation Time: Sep 09, 2016 at 11:50 PM
-- Server version: 10.1.16-MariaDB
-- PHP Version: 5.6.24
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `cars`
--
-- --------------------------------------------------------
--
-- Table structure for table `cars`
--
CREATE TABLE `cars` (
`ID` int(11) NOT NULL,
`car_name` text NOT NULL,
`car_brand` text NOT NULL,
`car_model` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `cars`
--
INSERT INTO `cars` (`ID`, `car_name`, `car_brand`, `car_model`) VALUES
(1, 'Nissan Patrol', 'Nissan', 2016),
(2, 'Camaro SS', 'Chevy', 2010),
(3, 'Mustang', 'Ford', 2013),
(4, 'S500', 'Mercedes', 2009),
(5, '330i', 'BMW', 2014);
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`ID` int(11) NOT NULL,
`username` text NOT NULL,
`password` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`ID`, `username`, `password`) VALUES
(1, 'androidworldbh', '123123'),
(2, 'user2', 'bahrain'),
(3, 'user3', '4567');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `cars`
--
ALTER TABLE `cars`
ADD PRIMARY KEY (`ID`);
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`ID`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `cars`
--
ALTER TABLE `cars`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
اسم قاعدة البيانات هو cars تحتوي على جدولين users,cars وكل جدول يحتوي على بيانات كما هو موضح في الكود السابق.
بعد ذلك قم بعمل ملف اسمه ولنفترض server.js يحتوي على التالي وبالتفصيل سأقوم بعرض الملف .. في البداية نستدعي مانريد من Packages
var http = require('http');
var express = require("express");
var cookieParser = require('cookie-parser');
var mysql = require('mysql');
var app = express();
نقوم بعمل الـRouting لنحدد للتطبيق المعني بالمتغير app كيفية استجابة طلب المتصفح ( العميل ) والـSyntax هو
app.METHOD(PATH, HANDLER);
في ملف server.js ستقوم بإضافة
app.use(cookieParser());
app.use('/bootstrap', express.static(__dirname + '/bootstrap'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/js', express.static(__dirname + '/js'));
app.use('/images', express.static(__dirname + '/images'));
app.use('/faawesome', express.static(__dirname + '/faawesome'));
لتستطيع استخدام الملفات الـCSS & JS وكذلك الصور , ولنستهل ربط قاعدة البيانات بالتطبيق من خلال الكود التالي:
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'cars'
});
ملاحظة: تستطيع استدعاء المتغيرات السابقة من ملف خارجي وبالغالب يتم تسميته بـconfig.js يحتوي على جميع المتغيرات الثابته constants مثل متغيرات ربط قواعد البيانات او ماشابه ذلك ولكن في هذا المثال سنستعمل الطريقة الإعتيادية والمباشرة.
وبهذا تم اعداد وربط قاعدة البيانات مع التطبيق, وبما ان هذا الدرس عبارة عن كيفية عمل تسجيل دخول سنقوم بكتابة كود الفورم داخل ملف login.html ( وسأفترض مسبقا بأنك تعرف ذلك ):
<div class="container">
<div class="card card-container">
<img id="profile-img" class="profile-img-card" src="images/nodejs-logo.png" />
<p id="profile-name" class="profile-name-card"></p>
<form class="form-signin" action="/api/login" method="get" id="loginForm">
<span id="reauth-email" class="reauth-email"></span>
<input type="text" id="username" class="form-control" placeholder="Username" name="username" required autofocus>
<input type="password" id="password" class="form-control" placeholder="Password" name="password" required>
<div id="remember" class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block btn-signin" type="submit">Sign in</button>
</form>
<a href="#" class="forgot-password" id="status">
Forgot the password?
</a>
</div>
</div>
سكربت ارسال بيانات فورم تسجيل الدخول في ملف الـhtml سيكون:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script>
$(document).ready(function() {
$('#loginForm').submit(function() {
$("#status").empty().text("loging in...");
$(this).ajaxSubmit({
error: function(xhr) {
status('Error: ' + xhr.status);
},
success: function(response) {
console.log(response)
if(response == 401){
$("#status").html("Error In Provided Info");
} else {
window.location.href = '/home/'+response;
}
}
});
return false;
});
});
</script>
نعود مرة اخرى لملف server.js ونضيف routing الفورم الذي بدوره يستقبل بيانات الدخول وهم اسم المستخدم username والباسسورد password ويطابق ما تم ارساله من قبل المستخدم مع ماهو موجود في جدول Users في قاعدة البيانات
app.get('/api/login', function (req, res) {
var user_credentials = {
username: req.query.username,
password: req.query.password
}
connection.query('SELECT * FROM users WHERE `username` = ?',user_credentials.username, function(err, rows, fields) {
if (err) throw err;
if(rows.length > 0){
var userpass = rows[0].password;
if(userpass == user_credentials.password){
console.log(JSON.stringify(user_credentials, null, 4));
res.send(user_credentials.username);
} else {
return res.json(401);
console.log("password aint right");
}
}
});
});
هنا نلاحظ عدة امور اولها الميثود المستخدم في هذا الـrouting او الـcontroller كما يستميه البعض وهي GET , ذلك يعني انه يجب على ميثود الفورم الذي عملته ان يكون GET ليستقبل البيانات
app.get
الملاحظة الثانية هي المتغيرين الأثنين وهم اسم المستخدم والباسسورد , تستطيع استخدامهم في الكود بشكل مباشر بهذه الطريقة
var username = req.query.username
var pssword = req.query.password
ولكن لسهولة التعامل قمنا بإضافتهم إلى متغير user_credentials بهذه الطريقة
var user_credentials = {
username: req.query.username,
password: req.query.password
}
ولأستدعاء اسم المستخدم مثلا:
user_credentials.username
ولمعلومات طرق عمل الـqueries الرجاء زيارة الرابط التالي:
https://www.npmjs.com/package/mysql
الملاحظة الثالثة وهي rows.length , عند execute الكويري, البكج المستخدم بشكل مباشر يقوم بإرجاع عدة بيانات تستطيع الإطلاع عليها في الـconsole وإحدى هذه الأمور هي عدد الصفوف التي هي متطابقة مع الكويري
connection.query('SELECT * FROM users WHERE `username` = ?',user_credentials.username, function(err, rows, fields) ...
وستكون بالعادة صف واحد, لذلك نضع شرط إذا كان عدد الصفوف المعنية بالكويري اكثر من صفر rows.length > 0 ذلك يعني بأن اسم المستخدم موجود في قاعدة البيانات ونطابق الـpassword كالتالي:
if(rows.length > 0){
var userpass = rows[0].password; // الباسسورد الذي تم استخراجه من الصف المرجع من الكويري
if(userpass == user_credentials.password){
console.log(JSON.stringify(user_credentials, null, 4));
res.send(user_credentials.username);
} else {
return res.json(401);
console.log("password aint right");
}
}
إذا كان كلمة المرور متطابقة, سنقوم بإرسال اسم المستخدم مرة اخرى لصفحة login.html لنرسلها إلى صفحة اخرى المعنية بحفظ الـcookies
res.send(user_credentials.username);
او اذا كانت كلمة المرور غير متطابقة سنرسل json عبارة عن
return res.json(401);
وفي ajax صفحة الـlogin.html
success: function(response) {
console.log(response)
if(response == 401){
$("#status").html("Error In Provided Info"); // إذا كان الكود المسترجع هو 401 ذلك يعني بأن كلمة السر غير متطابقة
} else {
window.location.href = '/home/'+response; // خلاف ذلك, سنرسل اسم المستخدم إلى روتنج معني بحفظ اسم المستخدم في كوكيز
}
}
إذا كانت كلمات السر متطابقة, ميثود الـAjax ستقوم بتحويل المستخدم إلى Routing لحفظ اسم المستخدم في كوكيز , وكود الـRounting هو:
app.get('/home/:user',function(req,res){
res.cookie('name', req.params.user).redirect('/home');
});
الذي بدوره يحفظ اسم المستخدم في كوكيز بعنوان name وبعد ذلك يحوله إلى صفحة الـhome.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Node.js Bootstrap 101</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<script src="/bootstrap/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script type="text/javascript">
$.ajax({
type: "GET",
url: '/api/cookies',
success: function(response) {
if(response != "undefined"){
$("#uls").append("<li><a href='logout'><i class='fa fa-lock'></i> Logout</a></li>");
$("#navbar").append("<ul class='nav navbar-nav navbar-right'><li><a href='#'><i class='fa fa-user'></i> Welcome Back. "+response+"</a></li></ul>")
} else {
window.location.href = '/login';
}
},
error: function(){
window.location.href = '/login';
}
});
</script>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Node.js</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav" id="uls">
<li class="active"><a href="#">Home</a></li>
<li><a href="about">About</a></li>
<li><a href="contact">Contact</a></li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div class="col-md-12">
<h1>Home Page</h1>
<h3>Bootstrap & NodeJS</h3>
</div>
</div>
</body>
</html>
و لا تنسى كتابة routing صفحتي الlogin and home و كذلك اللسنر في ملف server.js
app.get('/',function(req,res){
res.redirect("/home");
});
app.get('/home',function(req,res){
res.cookie('name', req.cookies.name).sendFile(__dirname + "/home.html");
});
app.get('/login',function(req,res){
res.sendFile(__dirname + "/login.html");
});
app.listen(3000,function(){
console.log("Working on port 3000");
});
وللتاكد بأنه تم حفظ اسم المستخدم سنعمل routing اخر وهو:
app.get('/api/cookies', function (req, res) {
if(res.cookie('name', req.cookies.name) != null){
res.send(req.cookies.name);
} else {
res.cookie('name', "undefined")
return res.json(401);
}
});
او من خلال console متصفح chrome بكتابة
اقتباسdocument.cookies
وبهذا, تستطيع تشغيل التطبيق الآن من خلال كوماند:
node server.js
و في المتصفح
127.0.0.1:3000/home
التعليقات (2)
شكراً على الدرس. رأيي بصراحة أنه من المهم اضافة التشفير في هذا الدرس حيث أنه من أساسيات التعامل مع قواعد بيانات المستخدمين وتسجيل عمليات الدخول.
8 ساعات مضت, alhadhrami said:شكراً على الدرس. رأيي بصراحة أنه من المهم اضافة التشفير في هذا الدرس حيث أنه من أساسيات التعامل مع قواعد بيانات المستخدمين وتسجيل عمليات الدخول.
هذه مجرد فقط البداية والسكيورتي سيكون عبارة عن ملاحظات لا اكثر خصوصا مع هذا البكج، حيث يعمل escape للvalues بشكل اوتوماتيكي
رغم ذلك، سيتم شرح الpool و الconnection.escape لاحقا
هناك تكمله لهذا الدرس كما تلاحظ بوجود جدول السيارات
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !