我的应用使用Express和AngularJS。我正在使用express通过静态来处理角度代码的基本网络搜索。角度代码使用命中由express托管的API端点的服务。我只希望在用户通过身份验证后可以访问API端点。我如何通过PassportJS实现这一目标?
答案 0 :(得分:17)
我已经在github上上传了一个我一直在研究的Angular-Express project。
它仍在进行中。我希望它有所帮助。
它使用PassportJ进行用户身份验证,是服务器端授权的基本示例。它演示了如何仅对经过身份验证的用户访问API调用,或仅对具有admin角色的用户进行访问。这是通过server/routes.js
调用ensureAuthenticated
ensureAdmin
和server/authentication.js
来实现的。
在routes.js中
// anybody can access this
app.get('/api/test/users',
api.testUsers);
// only logged-in users with ADMIN role can access this
app.get('/api/users',
authentication.ensureAdmin,
api.testUsers);
// only logged-in users can access this
app.get('/api/books',
authentication.ensureAuthenticated,
api.books);
在authentication.js
中ensureAuthenticated: function(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
return res.send(401);
}
},
ensureAdmin: function(req, res, next) {
// ensure authenticated user exists with admin role,
// otherwise send 401 response status
if (req.user && req.user.role == 'ADMIN') {
return next();
} else {
return res.send(401);
}
},
答案 1 :(得分:2)
我还没有使用passportjs,但我刚刚完成了你想做的事情。这是我的示例配置:
// Example configuration
var express = require('express');
var routes = require('./routes');
var app = express();
app.configure(function(){
app.use(express.bodyParser());
app.use(express.cookieParser('shhhh, very secret'));
app.use(express.session());
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.compress());
app.use('/', express.static(expressAppdir)); // look for overrides on express server 1st
app.use('/', express.static(appDir));
// app.use(express.methodOverride());
app.use(app.router);
app.use(function(req, res, next){
var err = req.session.error
, msg = req.session.success;
delete req.session.error;
delete req.session.success;
res.locals.message = '';
if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
next();
});
});
app.configure(function() {
// gets
app.get('/', routes.root);
app.get('/login', routes.login);
app.get('/logout', routes.logout);
app.get('/restricted/test/:slug', restrict, routes.restrictedGet); // must be last API route, slug is any request on the end of the routes that is requested.
app.post('/login', routes.loginPost);
});
function restrict(req, res, next) {
console.dir('restrict called');
if (req.session.user) {
next();
} else {
req.session.error = 'Access denied!';
res.redirect('/login');
}
}
//Routes.js file
// my dummy login (in a separate file)
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
exports.restrictedGet = function (req, res, next) {
console.dir('reached restricted get');
var slug = req.params.slug;
console.dir(req.route);
if(req.route.path.indexOf('test')!=-1)
{
namedQuery['testFunction'](req,res,next);
}
else
{
res.status(404).send('no route found. Route requested: ' + req.route.path);
}
// do something with your route here, check what's being appended to the slug and fire off the appropriate function.
};
exports.login = function(req, res, next) {
res.sendfile(serverBase + "/static/public/login.html");
};
exports.logout = function(req, res, next) {
req.session.destroy(function(){
res.redirect('/');
});
};
// this is where you would hook in your passportjs stuff to do hashing of inputted text and compare it to the hash stored in your db etc.
// I use my own simple authentication funciton right now as i'm just testing.
exports.loginPost = function(req, res, next) {
authenticate(req.body.username, req.body.password, function(err, user){
console.log('Reached login user: ', user);
if (user) {
// Regenerate session when signing in
// to prevent fixation
req.session.regenerate(function(){
req.session.user = user;
req.session.success = 'Authenticated as ' + user.name
+ ' click to <a href="/logout">logout</a>. '
+ ' You may now access <a href="/restricted">/restricted</a>.';
res.redirect('/');
});
} else {
req.session.error = 'Authentication failed, please check your '
+ ' username and password.'
+ ' (use "tj" and "foobar")';
res.json({success: false});
res.redirect('/login');
}
});
};
// You could now do this with passport instead:
exports.loginPost = function(req, res, next) {
passport.authenticate('local'), function(err, user){
console.log('Reached login user: ', user);
if (user) {
// Regenerate session when signing in
// to prevent fixation
req.session.regenerate(function(){
req.session.user = user;
req.session.success = 'Authenticated as ' + user.name
+ ' click to <a href="/logout">logout</a>. '
+ ' You may now access <a href="/restricted">/restricted</a>.';
res.redirect('/');
});
} else {
req.session.error = 'Authentication failed, please check your '
+ ' username and password.'
+ ' (use "tj" and "foobar")';
res.json({success: false});
res.redirect('/login');
}
};
};
function authenticate(name, pass, fn) {
var user = { name:name, password: pass }
return fn(null,user);
};
这是我从我的代码中获得的很多代码:http://www.breezejs.com/samples/zza,http://passportjs.org/guide/authenticate/
希望这有帮助!
#修改
#我忘了提到,对于角度方面,我只有一个简单的表格,将用户和密码的值发布回登录帖子端点,因为getEndpoint受限制,快递应用程序将处理其余的身份验证和限制对你而言的一面。如果我能得到任何进一步的帮助,请不要犹豫。
答案 2 :(得分:1)
这是检查用户是否已登录的非常简单的方法。
假设您设置了这样的中间件:
const authMiddleware = (req, res, next) => {
if(req.headers.authorization == undefined) { // or whatever auth strategy you're using
req.isAuthenticated = false;
}
else {
// your own code to fetch user
req.isAuthenticated = true;
}
next();
}
app.use(authMiddleware);
您可以创建另一个简单的中间件来限制某些路由:
const checkIsAuth = (req, res, next) => {
req.isAuthenticated ? next() : res.sendStatus(401);
}
router.get('/foo', checkIsAuth, fooController.getAll);
答案 3 :(得分:0)