인증기능 완성 - passport.js + bcrypt(3개 기능)
- user password hash 암호화(bcrypt) - login, logout 기능(passport.js) - 로그인 사용자만 페이지 액세스(passport - session)
Showing
8 changed files
with
277 additions
and
66 deletions
... | @@ -75,6 +75,11 @@ | ... | @@ -75,6 +75,11 @@ |
75 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", | 75 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", |
76 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" | 76 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" |
77 | }, | 77 | }, |
78 | + "bcrypt-nodejs": { | ||
79 | + "version": "0.0.3", | ||
80 | + "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", | ||
81 | + "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" | ||
82 | + }, | ||
78 | "bcrypt-pbkdf": { | 83 | "bcrypt-pbkdf": { |
79 | "version": "1.0.2", | 84 | "version": "1.0.2", |
80 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", | 85 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", |
... | @@ -880,6 +885,28 @@ | ... | @@ -880,6 +885,28 @@ |
880 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", | 885 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", |
881 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" | 886 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" |
882 | }, | 887 | }, |
888 | + "passport": { | ||
889 | + "version": "0.4.0", | ||
890 | + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", | ||
891 | + "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", | ||
892 | + "requires": { | ||
893 | + "passport-strategy": "1.0.0", | ||
894 | + "pause": "0.0.1" | ||
895 | + } | ||
896 | + }, | ||
897 | + "passport-local": { | ||
898 | + "version": "1.0.0", | ||
899 | + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", | ||
900 | + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", | ||
901 | + "requires": { | ||
902 | + "passport-strategy": "1.0.0" | ||
903 | + } | ||
904 | + }, | ||
905 | + "passport-strategy": { | ||
906 | + "version": "1.0.0", | ||
907 | + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", | ||
908 | + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" | ||
909 | + }, | ||
883 | "path-is-absolute": { | 910 | "path-is-absolute": { |
884 | "version": "1.0.1", | 911 | "version": "1.0.1", |
885 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", | 912 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", |
... | @@ -890,6 +917,11 @@ | ... | @@ -890,6 +917,11 @@ |
890 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | 917 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", |
891 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" | 918 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" |
892 | }, | 919 | }, |
920 | + "pause": { | ||
921 | + "version": "0.0.1", | ||
922 | + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", | ||
923 | + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" | ||
924 | + }, | ||
893 | "performance-now": { | 925 | "performance-now": { |
894 | "version": "2.1.0", | 926 | "version": "2.1.0", |
895 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", | 927 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", | ... | ... |
... | @@ -13,6 +13,7 @@ | ... | @@ -13,6 +13,7 @@ |
13 | "author": "", | 13 | "author": "", |
14 | "license": "ISC", | 14 | "license": "ISC", |
15 | "dependencies": { | 15 | "dependencies": { |
16 | + "bcrypt-nodejs": "0.0.3", | ||
16 | "body-parser": "^1.18.3", | 17 | "body-parser": "^1.18.3", |
17 | "cheerio": "^1.0.0-rc.2", | 18 | "cheerio": "^1.0.0-rc.2", |
18 | "ejs": "^2.6.1", | 19 | "ejs": "^2.6.1", |
... | @@ -20,6 +21,8 @@ | ... | @@ -20,6 +21,8 @@ |
20 | "express-session": "^1.15.6", | 21 | "express-session": "^1.15.6", |
21 | "iconv": "^2.3.1", | 22 | "iconv": "^2.3.1", |
22 | "mongoose": "^5.3.14", | 23 | "mongoose": "^5.3.14", |
24 | + "passport": "^0.4.0", | ||
25 | + "passport-local": "^1.0.0", | ||
23 | "request": "^2.88.0", | 26 | "request": "^2.88.0", |
24 | "selenium-webdriver": "^4.0.0-alpha.1" | 27 | "selenium-webdriver": "^4.0.0-alpha.1" |
25 | } | 28 | } | ... | ... |
1 | var express = require('express'); | 1 | var express = require('express'); |
2 | var app = express(); | 2 | var app = express(); |
3 | var bodyParser = require('body-parser'); | 3 | var bodyParser = require('body-parser'); |
4 | -//var session = require('express-session'); | 4 | +var session = require('express-session'); |
5 | var mongoose = require('mongoose'); | 5 | var mongoose = require('mongoose'); |
6 | +var passport = require('passport'); | ||
6 | 7 | ||
7 | //DB연결 | 8 | //DB연결 |
8 | -mongoose.connect('mongodb://username:pwd@1.201.139.92/dbname'); | 9 | +mongoose.connect('mongodb://username:pwd@host/dbname'); |
10 | +mongoose.Promise = global.Promise; | ||
9 | var db = mongoose.connection; | 11 | var db = mongoose.connection; |
10 | 12 | ||
11 | //연결실패 | 13 | //연결실패 |
... | @@ -20,10 +22,25 @@ db.once('open', function() | ... | @@ -20,10 +22,25 @@ db.once('open', function() |
20 | console.log('Connected!'); | 22 | console.log('Connected!'); |
21 | }); | 23 | }); |
22 | 24 | ||
23 | - | ||
24 | // DB모델정의 | 25 | // DB모델정의 |
25 | var Users = require('./models/users'); | 26 | var Users = require('./models/users'); |
26 | 27 | ||
28 | +// session | ||
29 | +app.use(session({ | ||
30 | + secret: 'keyboard cat', | ||
31 | + resave: false, | ||
32 | + saveUninitialized: true | ||
33 | +})); | ||
34 | + | ||
35 | +// passport setting | ||
36 | +require('./passport')(passport); | ||
37 | +app.use(passport.initialize()); | ||
38 | +app.use(passport.session()); //로그인 세션 유지 | ||
39 | +// 주의! passport.session을 사용하기 전에 app.use(session(~))설정을 해줘야 한다. | ||
40 | +// 그렇지 않으면 passport가 session을 사용하지 못한다. | ||
41 | +// app.use는 동기식으로 작동하기 때문에 순서에 유의해야한다. | ||
42 | + | ||
43 | + | ||
27 | // ejs사용 | 44 | // ejs사용 |
28 | // json사용설정 | 45 | // json사용설정 |
29 | app.set('view engine','ejs'); | 46 | app.set('view engine','ejs'); | ... | ... |
1 | var mongoose = require('mongoose'); | 1 | var mongoose = require('mongoose'); |
2 | +var bcrypt = require('bcrypt-nodejs'); | ||
2 | 3 | ||
3 | var userSchema = mongoose.Schema | 4 | var userSchema = mongoose.Schema |
4 | ( | 5 | ( |
... | @@ -9,5 +10,22 @@ var userSchema = mongoose.Schema | ... | @@ -9,5 +10,22 @@ var userSchema = mongoose.Schema |
9 | } | 10 | } |
10 | ); | 11 | ); |
11 | 12 | ||
13 | +// 패스워드 암호화 | ||
14 | +userSchema.methods.generateHash = function(password) | ||
15 | +{ | ||
16 | + // password hash를 만든다 | ||
17 | + return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); | ||
18 | +}; | ||
19 | + | ||
20 | +// 패스워드 검증 | ||
21 | +userSchema.methods.validPassword = function(password) | ||
22 | +{ | ||
23 | + // 기존의 해쉬값과 들어온 패스워드를 해쉬값으로 만든 값을 비교한다. | ||
24 | + // 주의! 기존의 값이 해쉬가 아니라면 비교불가. 따라서 에러. | ||
25 | + // 또한 나는 bcrypt를 bcryt로 잘못 썼는데 잘 안보인다... 조심해라... | ||
26 | + //var good = bcrypt.hashSync(this.pwd, bcrypt.genSaltSync(8), null); | ||
27 | + return bcrypt.compareSync(password, this.pwd); | ||
28 | +}; | ||
29 | + | ||
12 | module.exports = mongoose.model('user',userSchema); | 30 | module.exports = mongoose.model('user',userSchema); |
13 | 31 | ... | ... |
server_db/passport.js
0 → 100644
1 | +var LocalStrategy = require('passport-local').Strategy; | ||
2 | +var Users = require('./models/users'); | ||
3 | + | ||
4 | +module.exports = function(passport) | ||
5 | +{ | ||
6 | + passport.serializeUser(function(user, done) | ||
7 | + { | ||
8 | + done(null, user.id); | ||
9 | + }); | ||
10 | + | ||
11 | + passport.deserializeUser(function(id, done) | ||
12 | + { | ||
13 | + done(null, id); | ||
14 | + /* | ||
15 | + Users.findById(id, function(err, user) | ||
16 | + { | ||
17 | + done(err, user); | ||
18 | + }); | ||
19 | + */ | ||
20 | + }); | ||
21 | + | ||
22 | + // 회원가입 처리 | ||
23 | + passport.use('join', new LocalStrategy | ||
24 | + ( | ||
25 | + { | ||
26 | + usernameField: 'id', | ||
27 | + passwordField: 'pwd', | ||
28 | + passReqToCallback: true | ||
29 | + }, | ||
30 | + | ||
31 | + function(req, id, pwd, done) | ||
32 | + { | ||
33 | + Users.findOne({'id':id}, function(err, user) | ||
34 | + { | ||
35 | + if(err) return done(err); | ||
36 | + | ||
37 | + // 유저가 있을 경우 처리 | ||
38 | + if(user) | ||
39 | + { | ||
40 | + console.log("Duplicated user"); | ||
41 | + return done(null, false); | ||
42 | + } | ||
43 | + | ||
44 | + // 새로운 유저 DB추가처리 | ||
45 | + else | ||
46 | + { | ||
47 | + var newUser = new Users(); | ||
48 | + newUser.id = id; | ||
49 | + newUser.pwd = newUser.generateHash(pwd); | ||
50 | + | ||
51 | + // 로그인 이외 필요한 값들 추가 | ||
52 | + newUser.name = req.body.name; | ||
53 | + | ||
54 | + newUser.save(function(err) | ||
55 | + { | ||
56 | + if(err) throw err; | ||
57 | + return done(null, newUser); | ||
58 | + }); | ||
59 | + | ||
60 | + } | ||
61 | + }); | ||
62 | + })); | ||
63 | + | ||
64 | + // 로그인 처리 | ||
65 | + passport.use('login', new LocalStrategy | ||
66 | + ( | ||
67 | + { | ||
68 | + usernameField: 'id', | ||
69 | + passwordField: 'pwd', | ||
70 | + passReqToCallback: true | ||
71 | + }, | ||
72 | + function(req, id, pwd, done) | ||
73 | + { | ||
74 | + Users.findOne({'id': id}, function(err, user) | ||
75 | + { | ||
76 | + if(err) return done(err); | ||
77 | + | ||
78 | + // 유저가 없을 시 | ||
79 | + if(!user) | ||
80 | + { | ||
81 | + console.log('no user'); | ||
82 | + return done(null, false); | ||
83 | + //return done(null, false, req.flash('loginMessage', '없는 유저입니다..')); | ||
84 | + } | ||
85 | + | ||
86 | + // 틀린 비밀번호 | ||
87 | + if(!user.validPassword(pwd)) | ||
88 | + { | ||
89 | + console.log('bad password'); | ||
90 | + return done(null, false); | ||
91 | + //return done(null, false, req.flash('loginMessage', '비밀번호가 다릅니다.')); | ||
92 | + } | ||
93 | + | ||
94 | + console.log('login sucess'); | ||
95 | + return done(null, user); | ||
96 | + }); | ||
97 | + } | ||
98 | + )); | ||
99 | + | ||
100 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | module.exports = function(app, Users) | 1 | module.exports = function(app, Users) |
2 | { | 2 | { |
3 | + var passport = require('passport'); | ||
4 | + | ||
3 | app.get('/', function(req, res) | 5 | app.get('/', function(req, res) |
4 | { | 6 | { |
5 | - res.render("index"); | 7 | + // 로그인 중이면 메인페이지로 |
6 | - console.log("The index page!") | 8 | + if(req.isAuthenticated()) |
9 | + res.redirect("/main"); | ||
10 | + // 로그인 중이 아니라면 인덱스페이지 | ||
11 | + else | ||
12 | + { | ||
13 | + res.render("index"); | ||
14 | + console.log("The index page!"); | ||
15 | + } | ||
7 | }); | 16 | }); |
8 | - | 17 | + |
9 | // 로그인 수행 - POST | 18 | // 로그인 수행 - POST |
10 | - app.post('/login', function(req, res) | 19 | + app.post('/login', passport.authenticate('login', |
11 | { | 20 | { |
12 | - Users.find({id: req.body.id, pwd: req.body.pwd},{_id: 1}, function(err, user) | 21 | + successRedirect: '/main', |
13 | - { | 22 | + failureRedirect: '/' |
14 | - if(err) | 23 | + //failureFlash : true |
15 | - { | 24 | + })); |
16 | - console.log("Error!"); | ||
17 | - res.send("Error!") | ||
18 | - } | ||
19 | 25 | ||
20 | - // 매칭정보 없음 - 로그인 실패 | 26 | + // 로그아웃 수행 |
21 | - if(user.length==0) | 27 | + app.get('/logout', function(req, res) |
22 | - { | ||
23 | - console.log("Login failed!") | ||
24 | - res.send("Login_failed"); | ||
25 | - } | ||
26 | - | ||
27 | - // 매칭정보 있음 - 로그인 성공 | ||
28 | - else | ||
29 | - { | ||
30 | - console.log("Login Success!") | ||
31 | - res.redirect("/main"); | ||
32 | - // main으로 이동 | ||
33 | - } | ||
34 | - }); | ||
35 | - }); | ||
36 | - | ||
37 | - | ||
38 | - // 메인화면 - 로그인 후 기본 검색화면 | ||
39 | - app.get('/main', function(req,res) | ||
40 | { | 28 | { |
41 | - res.render("main"); | 29 | + req.logout(); |
42 | - console.log("The test page!") | 30 | + res.redirect('/'); |
43 | - }); | 31 | + }) |
44 | - | ||
45 | 32 | ||
46 | 33 | ||
47 | // Join | 34 | // Join |
... | @@ -50,30 +37,89 @@ module.exports = function(app, Users) | ... | @@ -50,30 +37,89 @@ module.exports = function(app, Users) |
50 | { | 37 | { |
51 | res.render("join") | 38 | res.render("join") |
52 | }) | 39 | }) |
53 | - .post(function(req, res) // 실제 Join 수행 - POST | 40 | + // 실제 Join 수행 - POST |
41 | + .post(passport.authenticate('join', | ||
54 | { | 42 | { |
55 | - // user정보 입력 | 43 | + successRedirect: '/main', |
56 | - var user = new Users(); | 44 | + failureRedirect: '/', |
57 | - user.id = req.body.id; | 45 | + //failureFlash : true |
58 | - user.pwd = req.body.pwd; | 46 | + })); |
59 | - user.name = req.body.name; | ||
60 | 47 | ||
61 | - // DB저장 | 48 | + |
62 | - user.save(function(err) | 49 | + // 메인화면 - 로그인 후 기본 검색화면으로 |
50 | + app.get('/main', function(req, res) | ||
51 | + { | ||
52 | + // 로그인 중이라면 | ||
53 | + if(req.isAuthenticated()) | ||
63 | { | 54 | { |
64 | - if(err) | 55 | + console.log("Logged in page"); |
65 | - { | 56 | + res.render("main"); |
66 | - console.log(err); | 57 | + } |
67 | - res.send("Error!") | 58 | + // 로그인 중이 아니라면 |
68 | - } | 59 | + else res.redirect("/"); |
69 | - else | ||
70 | - { | ||
71 | - console.log("Join Success"); | ||
72 | - res.redirect('/'); | ||
73 | - } | ||
74 | - }); | ||
75 | - }); | ||
76 | 60 | ||
61 | + }); | ||
77 | 62 | ||
78 | 63 | ||
79 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
64 | +} | ||
65 | + | ||
66 | + | ||
67 | + | ||
68 | + | ||
69 | + | ||
70 | +/* | ||
71 | +(구)직접 DB에 저장하기 | ||
72 | +.post(function(req, res) // 실제 Join 수행 - POST | ||
73 | +{ | ||
74 | + // user정보 입력 | ||
75 | + var user = new Users(); | ||
76 | + user.id = req.body.id; | ||
77 | + user.pwd = req.body.pwd; | ||
78 | + user.name = req.body.name; | ||
79 | + | ||
80 | + // DB저장 | ||
81 | + user.save(function(err) | ||
82 | + { | ||
83 | + if(err) | ||
84 | + { | ||
85 | + console.log(err); | ||
86 | + res.send("Error!") | ||
87 | + } | ||
88 | + else | ||
89 | + { | ||
90 | + console.log("Join Success"); | ||
91 | + res.redirect('/'); | ||
92 | + } | ||
93 | + }); | ||
94 | +}); | ||
95 | +*/ | ||
96 | + | ||
97 | +/* | ||
98 | +(구)직접 로그인 하기 | ||
99 | +app.post('/login', function(req, res) | ||
100 | +{ | ||
101 | + Users.find({id: req.body.id, pwd: req.body.pwd},{_id: 1}, function(err, user) | ||
102 | + { | ||
103 | + if(err) | ||
104 | + { | ||
105 | + console.log("Error!"); | ||
106 | + res.send("Error!") | ||
107 | + } | ||
108 | + | ||
109 | + // 매칭정보 없음 - 로그인 실패 | ||
110 | + if(user.length==0) | ||
111 | + { | ||
112 | + console.log("Login failed!") | ||
113 | + res.send("Login_failed"); | ||
114 | + } | ||
115 | + | ||
116 | + // 매칭정보 있음 - 로그인 성공 | ||
117 | + else | ||
118 | + { | ||
119 | + console.log("Login Success!") | ||
120 | + res.redirect("/main"); | ||
121 | + // main으로 이동 | ||
122 | + } | ||
123 | + }); | ||
124 | +}); | ||
125 | +*/ | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | <div class="contents_main"> | 1 | <div class="contents_main"> |
2 | - <form method="POST" action="/join"> | 2 | + <h1>This is main</h1> |
3 | - <label>id:</label><input type="text" name="id"><br/> | ||
4 | - <label>pwd:</label><input type="password" name="pwd"><br/> | ||
5 | - <label>name:</label><input type="text" name="name"><br/> | ||
6 | - <button type="submit">가입</button> | ||
7 | - </form> | ||
8 | </div> | 3 | </div> |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment