6 yıl önce 8 yorum
Merhabalar, bu bölümde ise oyuncumuzun giriş yapması için gerekli olan özellikleri ekleyeceğiz. Öncelikle kullanıcımızın veritabanımızdan şifresi ile giriş yapabilmesini sağlayacağız. Sonra ise google üzerinden oturum açabilmesini sağlayacağız.
Bu tür yapıları çeşitli platformlar üzerinde kullanmak için passport.js kullanacağız. Bu modül sadece google için değil Facebook, Twitter, OpenID gibi sistemler için de imkanlar sağlıyor. Ancak şu an için biz Google kullancağız. İleride diğer platformlar için destek ekleyebiliriz.
Passport.js ile ilgili bu makaleyi okumanızı tavsiye ederim.
npm i passport --save
kurulumu yaptıktan sonra server/uses.js dosyasında şu değişiklikleri yapalım:
const http = require('http');
const passport = require('passport');
...
app.use(bodyParser.json());
app.use(cookieParser());
app.use(passport.initialize()); // burada tanımladık
app.use(passport.session()); // oturum üzerinde değişiklik yapabilmesini istedik
...
Geçen hafta sanırsam bazı değişiklikleri anlamamışım örneğin users modelinin isExist methodunda değişiklik yapmışız. Bu değişiklik isExist modelinin eğer password ekliyse kullanıcıyı parolası ile aramasını sağlıyormuş. Biz de şöyle değişiklikler yapalım api/models/users.js modelindeki isExist methodunda:
isExist(email, password) {
...
query = query
.select([ // ve select üzerinde değişiklikler yapıldı
["id", "users.id"],
["name", "RTRIM(users.name)"],
["email", "RTRIM(users.email)"]
])
.exec();
return new Promise((resolve, reject) => {
...
if (res.rows.length > 0)
return resolve(res.rows[0]); // eskiden true dönüyordu şimdi kayıt
return resolve(false);
...
})
}
Bir de userPassword modelinde hatırlarsanız crypto yapan bir satır vardı bunu diğer yerlerde de kullanmak için crypto adında bir methoda çevridik. userPassword modeli de şöyle değişti:
const database = require('../../database');
const sm = require('sqlmaster');
const crypto = require('crypto');
class UserPassword {
crypto(str) {
return crypto.pbkdf2Sync(str, 'satranc', 100000, 64, 'sha512').toString('hex');
}
insert(id, password) {
return new Promise((resolve, reject) => {
if (!password) {
reject(new Error('password is null'));
}
password = this.crypto(password); // burada çağrıldı
...
Şimdi passport'u kullanmak için controllers/auth.js dosyasını oluşturalım:
const passport = require('passport');
module.exports = (request, response, next) => {
switch (request.query.type) {
case 'user':
// yazılacak
break;
case 'google':
// yazılacak
break;
default:
response.status(400);
response.end();
break;
}
};
NOT: Her controller ve model'i oluşturduktan sonra kesinlikle controlles/index.js ve models/index.js dosyasında belirtmeyi unutmayın.
Bir de bunu /v1/auth?type=user şeklinde çağrılması için routes üzerinde belirtelim.
...
module.exports = {
post: {
...
'/v1/auth': auth,
},
get: {
...
'/v1/auth': auth,
},
...
Hem get'e hem de post'a ekledik çünkü google üzerinden oturum doğrulamak için POST kullanmak, yeni bir tarayıcı sekmesinde oturum açabilmeyi olanaksız kılıyor. window.open('/v1/auth?type=google')
gibi düşünebilirsiniz.
Passport'u istenildiği gibi local veritabanından kontrol etmek için passport-local modülünü kullanacağız. Kurmak için:
npm install passport-local --save
Şimdi uses.js dosyasında kullanalım:
...
const passport = require('passport');
const LocalStrategy = require('passport-local');
// doğrulamayı bu model yaptığı için buraya aldık.
// MVC yapısını bozmuş olsada böyle olabileceğini düşündüm.
const {
Users,
} = require('./api/models');
module.exports = (app) => {
...
app.use(passport.initialize());
app.use(passport.session());
// Bunlar session kullandığımız için gerekli bkz: https://github.com/jaredhanson/passport#sessions
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
// burada bir Strategy kullanmasını sağlıyoruz
passport.use(
new LocalStrategy((username, password, done) => {
// kullanıcıyı getiriyoruz
Users.isExist(username, password).then(user => {
// kullanıcı gelmişse done methodunu ona göre çağırıyoruz
if (user !== false) return done(null, user);
done(null, false);
}, err => {
done(err);
})
})
);
...
}
Şimdi auth controller'ına gelen isteğin passport kullanmasını sağlayalım. Bunun için controllers/auth.js dosyasını şöyle düzenleyelim:
const passport = require('passport');
module.exports = (request, response, next) => {
switch (request.query.type) {
case 'user':
passport.authenticate('local', (err, user) => {
// uses'a yazdığımı done methodu burayı tetikliyor
if (user !== false) {
request.session.auth = true;
} else {
request.session.auth = false;
}
response.send({
auth: request.session.auth
});
})(request, response, next);
break;
case 'google':
// Yapılacak
break;
default:
response.status(400);
response.end();
break;
}
};
Şimdi localhost:3000/v1/auth?type=user adresine username ve password değerleriyle istek attığımızda gelen cevabı görebiliriz.
Passport'u google üzerinden oturum açmasını sağlamak için passport-google-oauth2 modülünü kullanacağız (bkz: Google Auth 1.0'ı kullanımdan kaldırdı). Kurmak için:
npm i passport-google-oauth2 --save
Burada bizi bekleyen bir controller daha var çünkü google auth için yönlendirme üzerinden çalışıyor. Bundan önce biz uses.js üzerinde passport'a use edelim. Bunun için uses.js dosyasını düzenliyoruz:
...
const GoogleStrategy = require('passport-google-oauth20');
const config = require('./config');
const {
Users,
} = require('./api/models');
module.exports = (app) => {
...
passport.use(
new GoogleStrategy({
clientID: config.google.GOOGLE_CLIENT_ID,
clientSecret: config.google.GOOGLE_CLIENT_SECRET,
callbackURL: "/v1/auth/callback/google", // burayı oluşturacağız
}, (accessToken, refreshToken, profile, done) => {
// burada o kişiye ait bilgiler geliyor ancak biz kaydetmiyoruz şu an için
// yani burası yapılacak, test için verileri yazdırıyoruz
console.log(JSON.stringify(profile));
return done(null, accessToken);
})
);
...
}
Burada verdiğimiz config değerindeki veriler sizin uygulamanızda vermeniz gereken google değerleri. Bunları config.js dosyasına eklemelisiniz:
module.exports = {
...
google: {
GOOGLE_CLIENT_ID: "...",
GOOGLE_CLIENT_SECRET: "...",
}
}
Bu değerler size ait olmalı. Elde etmek için console.developers.google.com.
Şimdi, biraz önce belirttiğimiz callbackURL değerine yazdığımız router'ı oluşturalım. Bunun için api/controllers/callback.js diye bir dosya oluşturuyoruz:
module.exports = {
success: (request, response) => {
request.session.auth = true;
response.redirect('/');
},
error: (request, response) => {
request.session.auth = false;
response.redirect('/');
}
}
şimdi routes.js dosyasında değişiklikler yapalım:
const {
...
callback,
} = require('./controllers');
...
const passport = require('passport');
module.exports = {
...
get: {
...
'/v1/auth/callback/error': callback.error,
'/v1/auth/callback/google': [
passport.authenticate('google', { failureRedirect: '/v1/auth/callback/error' }),
callback.success,
]
},
Dikkat ederseniz direkt bir method vermek yerine bir dizi verdik. express bize böyle bir imkan sağlıyor. Burada passport.authenticate('google')
middleware işlevini görüyor. Bir de dikkat etmemiz gereken bir nokta da ana dizine (/) redirect yapmamız. Bu router'ı bulamadığı içi 404 verecektir. Biz ana dizin için bir boş sayfa açalım. Bunu da home controller'ı oluşturalım ve orada yapalım. controllers/home.js şöyle olsun
module.exports = (request, response) => {
response.end('');
}
routes.js üzerinde de belirtelim ve yukarı home controller'ını dahil etmeyi unutmayalım:
...
home,
} = require('./controllers');
...
module.exports = {
...
get: {
'/': home,
...
},
...
}
şimdi http://localhost:3000/v1/auth?type=google adresine girdiğimizde ve giriş yaptığımızda ana dizine (/) yönlendirileceğiz.
Bu gün anlatacaklarım bu kadardır. Diğer bölümde görüşmek üzere kendinize iyi bakın :)
Düşündüklerin nedir ?
Yorumlar ({{totalCommentCount}})
{{commentLike74Count}} beğenme 6 yıl önce
{{commentLike101Count}} beğenme 5 yıl önce
{{commentLike102Count}} beğenme 5 yıl önce
{{commentLike107Count}} beğenme 5 yıl önce
{{commentLike108Count}} beğenme 5 yıl önce
{{commentLike148Count}} beğenme 4 yıl önce
{{commentLike166Count}} beğenme 3 yıl önce
{{commentLike167Count}} beğenme 3 yıl önce