
JWT Login&Register Panel | Node.JS & MySQL
Herkese selamlar arkadaşlar, uzun zamandır hem iş gereği hem de kişisel projelerimden ötürü .net etkisinden bir türlü çıkamadığımı fark ettim. Daha önce ki yıllarda .Net dışında Php, Node.JS, ve Swift ile (*web ve mobil alanlarda) geliştirdiğim projeleri hem unutmamak hem de sizlere bir şeyler öğretmek için tekrar ele alacağım.
Şimdi senaryomuza bakacak olursak.. JWT,MySQL ile giriş ve kayıt olmayı en basit şekilde kurgulayalım.

Node.JS işlerimize başlamadan önce MySQL serverimiz de “NodeLoginDB” adında bir database oluşturalım.
CREATE TABLE `tbllogin` | |
( | |
`Id` int(11) NOT NULL, | |
`Username` varchar(15) NOT NULL, | |
`Password` text NOT NULL, | |
`Email` varchar(100) NOT NULL | |
) | |
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | |
ALTER TABLE `tbllogin` ADD PRIMARY KEY (`Id`); | |
ALTER TABLE `tbllogin` MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, | |
AUTO_INCREMENT=7; | |
COMMIT; |

Veritabanımızı başarılı bir şekilde oluşturduktan sonra Node.JS’e geri dönüp hemen terminalden veya bash’den gereken paketleri kuralım:)
- Terminal veya bash >
- npm install hbs
- npm install bcryptjs
- npm install cookie-parser
- npm install dotenv
- npm install jsonwebtoken
- npm install mysql
- npm install -g nodemon
Ana dizine app.js adında bir script oluşturup kurduğumuz paketlerin gerekli bir kısımını Importlamaya başlıyalım:)
// Imports | |
const express = require('express') | |
const app = express() | |
const dotenv = require('dotenv'); | |
const cookieParser = require('cookie-parser'); |
CSS, JS ve Images dosyalarımızı projemizin assets klasörüne dahil etmeyi de unutmayalım:)
// Static files | |
app.use(express.static('assets')) | |
app.use('/css', express.static(__dirname + 'assets/css')) | |
app.use('/js', express.static(__dirname + 'assets/js')) | |
app.use('/images', express.static(__dirname + 'assets/images')) | |
// Auth Css/Jss/Image | |
app.use('/auth/css', express.static(__dirname + '/assets/css')) | |
app.use('/auth/js', express.static(__dirname + '/assets/js')) | |
app.use('/auth/images', express.static(__dirname + '/assets/images')) |
Projemizin view katmanını Handlebars (.hbs) ile yapacağımız için view engine’miz de belirtiyoruz ve ana dizine views adında bir klasör oluşturuyoruz.
app.set('view engine', 'hbs') |
Cookies ve json işlemleri için klasik encodedleri de app.use ile ekliyoruz.
//Encoded | |
app.use(express.urlencoded({ extended: false })); | |
app.use(express.json()); | |
app.use(cookieParser()); |
Routes ayarları yapmak için ana dizine Routes adında bir klasör oluşturalım ve içine auth.js atında bir script oluşturalım.
// Define Routes | |
app.use('/', require('./routes/pages')); | |
app.use('/auth', require('./routes/auth')); |
Bütün işlemleri yaptıktan sonra app.js scriptimiz bu şekilde olacaktır.
// Imports | |
const express = require('express') | |
const app = express() | |
const dotenv = require('dotenv'); | |
const cookieParser = require('cookie-parser'); | |
const Port = 8000 | |
// DotENV Confing | |
dotenv.config({ path: './env'}) | |
// Static files | |
app.use(express.static('assets')) | |
app.use('/css', express.static(__dirname + 'assets/css')) | |
app.use('/js', express.static(__dirname + 'assets/js')) | |
app.use('/images', express.static(__dirname + 'assets/images')) | |
// Auth Css/Jss/Image | |
app.use('/auth/css', express.static(__dirname + '/assets/css')) | |
app.use('/auth/js', express.static(__dirname + '/assets/js')) | |
app.use('/auth/images', express.static(__dirname + '/assets/images')) | |
app.set('view engine', 'hbs') | |
//Encoded | |
app.use(express.urlencoded({ extended: false })); | |
app.use(express.json()); | |
app.use(cookieParser()); | |
// Define Routes | |
app.use('/', require('./routes/pages')); | |
app.use('/auth', require('./routes/auth')); | |
// Listen on port 8000 | |
app.listen(Port, () => console.info(`Listening on port ${Port} succesfully!`)) |
Burada routing mantığını iyice kavramanız gerekiyor, yanlış bir routing yaparsanız <form action=”…”> veya herhangi bir yönlendirme de yanlış adrese gider durursunuz o yüzden app.js bittikten sonra iyice kodları okuyup, bu kod nasıl işliyor/nasıl yönleniyor diye bakmanızda fayda var 🙂


Şimdi sitemize ../auth olarak gelen requestleri yönlendirmek için ana dizine routes klasörünü açıp auth.js scriptini oluşturalım.
const express = require('express'); | |
const authController = require('../controllers/auth'); | |
const router = express.Router(); | |
// Routers | |
router.post('/login', authController.login) | |
router.post('/register', authController.register) | |
module.exports = router; |
Eveeett routing,asset vb ayarlamaları yaptıktan sonra şimdi sıra geldi MySQL‘e bağlanmamıza…
Ana dizinimize .env adında bir settings dosyası oluşturalım ve database bilgilerimizi yazalım.
DB_NAME = NodeLoginDB | |
DB_HOSTNAME = localhost | |
DB_USERNAME = root | |
DB_PASSWORD = |
routes/auth.js‘den gelen ../login ve ../register requestleri yönlendirecek olan controllers klasörü açıp, içine auth.js scriptini oluşturalım.
const mysql = require('mysql') | |
const jwt = require('jsonwebtoken') | |
const bcrypt = require('bcryptjs') | |
require('dotenv').config() | |
// MySQL Connection | |
const dB = mysql.createConnection({ | |
host: process.env.DB_HOSTNAME, | |
user: process.env.DB_USERNAME, | |
password: process.env.DB_PASSWORD, | |
database: process.env.DB_NAME | |
}) | |
dB.connect((error)=>{ | |
if(error){ | |
console.log(error) | |
} else{ | |
console.log("MYSQL Connected!") | |
} | |
}) |
Şimdi MySQL bağlantısını kontrol edebilmek için ” npm run start ” yazarak localhost’u hayata kaldırıyorum..

Leeeeeeeetttsss goo…

Evet projemiz başarıyla MySQL’e bağlandığını görüyoruz:) Şimdi github’da paylaştığım tasarımı projemize dahil ediyoruz eğer sizin beğendiğiniz bir login®ister page var ise onu projenize ekleyebilirsiniz. *NOT* Kendi tasarımınızı kullanacak iseniz <form action=”/auth/login” method=”POST”> bölümünü eklemeyi unutmayınız.
Label Admin Template Source;
- assets : https://github.com/dgokhan/NodeJS-LabelAdminPanel/tree/main/assets
- views : https://github.com/dgokhan/NodeJS-LabelAdminPanel/tree/main/views
Githubda ki assets klasörünü ve views .hbs’leri indirip projeye dahil ettiğimize göre sıra auth.js‘e kayıt olma ve giriş yapma methodlarını eklemeye geldi..
#Register
exports.register = (req,res) => { | |
console.log(req.body); | |
const { email, username, password, repassword } = req.body; // requestten json ile serialize edilmiş veriyi değişkenlere ata. | |
// SQL' de böyle bir kullanıcı varmı sorgusu.. | |
dB.query('SELECT username FROM tblLogin WHERE username = ?', [username], async (error, results) => { | |
if(error){ | |
console.log(error); | |
} | |
if(results.length > 0){// Böyle bir kullanıcı var ise.. | |
return res.render('register', { | |
message: 'That username is already in use' | |
}) | |
} | |
else if( password !== repassword){ // Şifre tekrarı birbiriyle aynı mı kontrol.. | |
return res.render('register'),{ | |
message: 'Password do not match!' | |
} | |
} | |
// Kullanıcın şifresini hashle! | |
let hashedPassword = await bcrypt.hash(password, 8); | |
console.log(hashedPassword); //Kullanıcıyı veri tabanına kaydetme işlemi. | |
dB.query('INSERT INTO tblLogin SET ?', {Username: username, Password: hashedPassword, Email: email}, (error, results)=>{ | |
if(error){ | |
console.log(error); | |
}else{ | |
console.log(results); | |
return res.render('register', { | |
message:'User registered!' | |
}); | |
} | |
}); | |
}) | |
} |
Kayıt olma bölümünde ilk önce kullanıcının bize gönderdiği kullanıcı adı ile veritabanında arama yapıyoruz. Eğer o kullanıcı adına sahip birisi var ise ‘That username is already in use’ bilgisini dönüyoruz eğer böyle bir kullanıcı yok ise kullanıcının şifresinin hashlenmiş halini veritabanına gönderip üye olmasını sağlıyoruz:)
Unutmayın.. ne olursa olsun hiçbir zaman database’ye görünür bir şekilde şifre kaydetmeyiz! Şirketlerin kendilerine göre yazdığı şifreleme ile veya MD5 gibi şifrelemeler ile şifrelenir. Bizde şifrelerimiz açık bir şekilde gözükmemesi için bcrypt ile şifremizi hashleyeceğiz. Böylelikle olası bir database saldırısı sonucunda verilerimiz çalınsa bile müşterilerimizin şifrelerini bulmalarını zorlaştıracağız..
Yukarda bahsi geçen abimiz bu kadarcık bir kod 🙂
let hashedPassword = await bcrypt.hash(password, 8); |
#Login
exports.login = (req, res) =>{ | |
const{username,password} = req.body; | |
if(!username || !password){ | |
return res.status(400).render('login', { | |
message: 'Please provide an username and password!' | |
}) | |
} | |
// Kullanıcı bilgisini sorgulayan query... | |
dB.query('SELECT * FROM tblLogin WHERE Username = ?', [username], async (error, results) => { | |
if(!(await bcrypt.compare(password, results[0].Password))){ | |
res.status(401).render('login', { | |
message: 'Username or Password is incorrect!' | |
}) | |
} else{ | |
const dbUsername = results[0].Username; // Veritabanından gelen kullanıcı adını dbUsername değişkenine gönder. | |
const token = jwt.sign({dbUsername}, process.env.JWTSECRETKEY); // belirlediğiniz JWTSECRETKEY ve dBUsername ile token kodunu oluştur. | |
res.cookie('jwt', token, {maxAge: 20000, httpOnly:true}); // oluşturulan token kodunu jwt adında cookielere kaydet! | |
res.status(200).redirect("/"); // Başarılı bir şekilde anasayfaya yönlen.. | |
} | |
}); | |
} |
JWT ile ilgili kodlarımız;
const dbUsername = results[0].Username; | |
const token = jwt.sign({dbUsername}, process.env.JWTSECRETKEY); | |
res.cookie('jwt', token, {maxAge: 20000, httpOnly:true}); | |
res.status(200).redirect("/"); |
maxAge: 20000 bırakırsanız giriş yaptıktan 20 saniye sonra token ölecektir ve kullanıcıyı tekrar login sayfasına yönlendirecektir. Eğer tokenin 1saatte ölmesini istiyorsanız maxAge: 3600000 yapmanız gerekmektedir. (1saniye = 1000ms ‘den istediğiniz dakikayı ayarlayabilirsiniz. (1000*60)*dakika )
Şimdi localhost:8000‘i yenileyip localhost:8000/register sayfasına gidelim ve kayıt bilgilerimizi girelim:)

Evet başarıyla kullanıcı kaydımızı olduk fakat bildirim yeşil yerine kırmızı bir uyarı gibi olmuş, bunlar hep hızlı kod yazayım derken copy&paste hatalarınadn:).. neyse orayı makaleyi paylaşmadan hemen önce düzenlerim:p Bu arada gelin veritabanımıza bir bakalım:)

Kayıt olma başarılı ✔️bir de giriş yapmayı deneyelim bakalım..



Şimdi database işlemlerimiz ve token oluşturmamız tamam geriye sadece siteye giriş yaptıktan sonra cookies’de ki token kodunu kontrol etmek kaldı..
Hemen routes/pages.js‘e geri gelip verifyToken adında bir function açalım..
const verifyToken = (req, res, next) => { | |
const token = req.cookies.jwt // cookiesde ki jwt adında ki token kodunu token değişkenine gönder. | |
try { | |
if (!token) { // token boş ise.. | |
return res.status(401).redirect("/login"); | |
} | |
const decrypt = jwt.verify(token, process.env.JWTSECRETKEY); // cookiesde ki token kodu ile oluşturduğumuz secretkeyle kontrol et. | |
req.user = { | |
firstname: decrypt.username, | |
}; | |
} catch (err) { | |
return res.status(500).json(err.toString()); | |
} | |
}; |
Ardından ../ anasayfaya yapılan requestlere verifyToken yapıp tokeninin yaşayıp/yaşamadığını kontrol ettirelim.
// Routers | |
router.get('/', (req,res) =>{ | |
verifyToken(req,res); | |
res.render('index') | |
}) |
Eğer token yaşıyor ise kullanıcı hiç bir sorun yaşamadan sitede ki işlemlerini yapmaya devam edecektir.
Fakat token süresi biter ise kullanıcı direk giriş yapma ekranına yönlendirelecektir.
Proje ağacımızın son hali;

Bu yazımızında sonuna geldik. Bu makalede NodeJS & MySQL veritabınında ki kullanıcıyı JWT kontrolü ile giriş yapmayı ve veritabanına kaydolmayı anlatmaya çalıştım.
Eğer projelerden vakit bulabilrsem yakında NodeJS, Swift ve Xamarin dersleri de çıkarmaya çalışacağım.
Sağlıkla ve yazılımla kalmanız dileğiyle, hamınızı öpürem. 🇦🇿 🇹🇷 🖥️