Skip to content

Commit

Permalink
Node.js+Mongoose的RestfulApi的用户token权限验证具体代码
Browse files Browse the repository at this point in the history
  • Loading branch information
nicksapp committed Dec 1, 2016
0 parents commit c57fac0
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
md/
4 changes: 4 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
'secret': 'learnRestApiwithNickjs', // used when we create and verify JSON Web Tokens
'database': 'mongodb://localhost:27017/test' // 填写本地自己 mongodb 连接地址,xxx为数据表名
};
25 changes: 25 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const express = require('express');
const app = express();
const bodyParser = require('body-parser');// 解析body字段模块
const morgan = require('morgan'); // 命令行log显示
const mongoose = require('mongoose');
const passport = require('passport');// 用户认证模块passport
const Strategy = require('passport-http-bearer').Strategy;// token验证模块
const routes = require('./routes');
const config = require('./config');

let port = process.env.PORT || 8080;

app.use(passport.initialize());// 初始化passport模块
app.use(morgan('dev'));// 命令行中显示程序运行日志,便于bug调试
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json()); // 调用bodyParser模块以便程序正确解析body传入值

routes(app);

mongoose.Promise = global.Promise;
mongoose.connect(config.database); // 连接数据库

app.listen(port, () => {
console.log('listening on port : ' + port);
})
50 changes: 50 additions & 0 deletions models/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const bcrypt = require('bcrypt');

const UserSchema = new Schema({
name: {
type: String,
unique: true,
require: true
},
password: {
type: String,
require: true
},
token: {
type: String
}
});

// 添加用户保存时中间件对password进行bcrypt加密,这样保证用户密码只有用户本人知道
UserSchema.pre('save', function (next) {
var user = this;
if (this.isModified('password') || this.isNew) {
bcrypt.genSalt(10, function (err, salt) {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
});
});
} else {
return next();
}
});
// 校验用户输入密码是否正确
UserSchema.methods.comparePassword = function(passw, cb) {
bcrypt.compare(passw, this.password, (err, isMatch) => {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
};

module.exports = mongoose.model('User', UserSchema);
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "auth",
"version": "1.0.0",
"description": "基于node.js+express+mongodb的restful api开发用户模型认证相关",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Nickj",
"license": "ISC",
"dependencies": {
"bcrypt": "^0.8.7",
"body-parser": "^1.15.2",
"express": "^4.14.0",
"jsonwebtoken": "^7.1.9",
"mongoose": "^4.7.1",
"morgan": "^1.7.0",
"passport": "^0.3.2",
"passport-http-bearer": "^1.0.1"
}
}
23 changes: 23 additions & 0 deletions passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const passport = require('passport');
const Strategy = require('passport-http-bearer').Strategy;

const User = require('./models/user');
const config = require('./config');

module.exports = function(passport) {
passport.use(new Strategy(
function(token, done) {
User.findOne({
token: token
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false);
}
return done(null, user);
});
}
));
};
7 changes: 7 additions & 0 deletions routes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = (app) => {
app.get('/', (req, res) => {
res.json({ message: 'hello index!'});
});

app.use('/api', require('./users')); // 在所有users路由前加/api
};
75 changes: 75 additions & 0 deletions routes/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const express = require('express');
const User = require('../models/user');
const jwt = require('jsonwebtoken');
const config = require('../config');
const passport = require('passport');
const router = express.Router();

require('../passport')(passport);

// 注册账户
router.post('/signup', (req, res) => {
if (!req.body.name || !req.body.password) {
res.json({success: false, message: '请输入您的账号密码.'});
} else {
var newUser = new User({
name: req.body.name,
password: req.body.password
});
// 保存用户账号
newUser.save((err) => {
if (err) {
return res.json({success: false, message: '注册失败!'});
}
res.json({success: true, message: '成功创建新用户!'});
});
}
});

// 检查用户名与密码并生成一个accesstoken如果验证通过
router.post('/user/accesstoken', (req, res) => {
User.findOne({
name: req.body.name
}, (err, user) => {
if (err) {
throw err;
}
if (!user) {
res.json({success: false, message:'认证失败,用户不存在!'});
} else if(user) {
// 检查密码是否正确
user.comparePassword(req.body.password, (err, isMatch) => {
if (isMatch && !err) {
var token = jwt.sign({name: user.name}, config.secret,{
expiresIn: 10080
});
user.token = token;
user.save(function(err){
if (err) {
res.send(err);
}
});
res.json({
success: true,
message: '验证成功!',
token: 'Bearer ' + token,
name: user.name
});
} else {
res.send({success: false, message: '认证失败,密码错误!'});
}
});
}
});
});

// passport-http-bearer token 中间件验证
// 通过 header 发送 Authorization -> Bearer + token
// 或者通过 ?access_token = token
router.get('/user/user_info',
passport.authenticate('bearer', { session: false }),
function(req, res) {
res.json({username: req.user.name});
});

module.exports = router;

0 comments on commit c57fac0

Please sign in to comment.