【问题标题】:RESTful Node.js Application with passport-http带有护照-http 的 RESTful Node.js 应用程序
【发布时间】:2016-05-18 20:53:31
【问题描述】:

我正在努力让passport-http 与我的应用程序一起工作,以使其符合RESTful 原则。

现在的默认设置是浏览器使用自己的提示提示用户输入用户名和密码。

使用 Node.js 和 PassportJS 是否可以使用我自己的登录表单?如果用户尝试访问他们未通过身份验证的页面,那么我会将他们重定向到该表单。还是这本身就违反了RESTful设计的原则?

【问题讨论】:

  • passport 允许您制作自己的登录表单。您想使用本地策略。 passportjs.org/docs/username-password 。通过使用护照,您将允许用户登录,并且用户将只能看到他们的数据。
  • 快速谷歌搜索返回github.com/jaredhanson/passport-local 这是你用来实现你自己的登录表单的。将用户名和密码从您的表单发布到您的服务器并使用本地护照
  • 但这不是 RESTful 因为会话。

标签: node.js rest passport.js


【解决方案1】:

这是您在服务器文件中创建用户和密码身份验证所需的内容。您需要包含 localStategy,配置护照,并使用序列化和反序列化方法。下面的作品。

var express = require("express");
var app = express();
var passport = require("passport");
var flash = require("connect-flash");
var LocalStrategy = require("passport-local").Strategy;
var mongoose = require("mongoose");
var bodyParser = require("body-parser");
var session = require("express-session");
var cookieParser = require("cookie-parser");

app.use(bodyParser.urlencoded({extended : false}));
app.use(bodyParser.json());

app.use(cookieParser());

app.use(session({
    secret : "keyboard cat",
    resave : false,
    saveUninitialized : true
}))

app.use(flash());

app.use(passport.initialize());
app.use(passport.session());



mongoose.connect("mongodb://localhost/passport", function(){
    console.log("connected")
})

var userSchema = new mongoose.Schema({
    username : String,
    password : String,
})

userSchema.methods.validPassword = function(pwd){
    return (this.password === pwd)
}
var User = mongoose.model("User", userSchema)



passport.use("local", new LocalStrategy(
    function(username, password, done){
        User.findOne({ username : username}, function(err, user){
            if(err){return done(err);}
            if(!user){
                console.log("no user")
                return done(null, false,{message : "Incorrect username."});
            }
            if(!user.validPassword(password)){
                return done(null, false,{message : "Incorrect password."});
            }
            return done(null, user)
        })
    }))

passport.serializeUser(function(user, done){ // change done to cb
    done(null, user);
})

passport.deserializeUser(function(user, done){
    User.findOne(user, function(err, user){
        console.log("myerr" + err)
        done(err, user)
    })
})


app.set("views", "./views");
app.set("view engine", "jade");

app.get("/signup", function(req, res){
    res.render("signup")
})

app.post("/signup", function(req, res){
    User.create({"username" : req.body.username, "password" : req.body.password}, function(err, doc){
        console.log(doc);

    })
    res.redirect("/login")
})

app.get("/login", function(req, res){
    res.render("login")
})

app.post("/login", function(req, res, next){
    passport.authenticate("local", function(err, user, info){
        if(err){return next(err); }
        if(!user){return res.redirect("/login");}
            req.logIn(user, function(err){
                if(err){ return next(err);}
                return res.redirect("/users/" + user.username)
            })
    })(req, res, next);
})

app.get("*", function(req, res){
    res.send("EVERYTHANG")
})

app.listen(3000, function(){
    console.log("listening on 3000")
})

login.jade:

html
    head
        title LogIN
    body
        form(method = "POST", action = "/login")
            label username
            input(type = "text", name = "username")
            br
            label password :
            input(type = "text", name = "password")
            button(type="submit") LogIN

signup.jade:

html
    head
        title signup
    body
        form(method = "POST", action= "/signup")
            label username
            input(type = "text", name = "username")
            br
            label password :
            input(type = "text" , name = "password")
            button(type="submit") Signup

【讨论】:

  • 我知道如何执行本地策略,但我的印象是会话不是 RESTful。
【解决方案2】:

REST 定义 Web 服务。服务与 UI 无关。

理论上,您应该使用 fiddler、firebug、postman 或类似工具来测试您的服务。

您的 UI 选择是完全独立的。

如果您需要某人能够进行身份验证,那么您将需要处理对用户进行身份验证的请求的视觉呈现。

如果您查看护照文件,它们会显示基本身份验证的示例:

app.post('/login', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login'}));

在这种情况下,如果成功,身份验证会将用户重定向到网站根目录定义的页面,否则用户将被重定向到 /login 提供的页面。

在任何一种情况下,登录尝试都是来自网络服务器提供的页面的 post 方法。

passportjs docs

【讨论】:

  • 我如何让本地护照成为 RESTful?
  • 如果用户必须经过身份验证,那么您必须使用某种令牌。会话只是一个令牌。 IMO 符合要求,因为您没有维护有状态的连接,而是使用 cookie 来维护该会话。
  • 很公平,您可以将{ session : false }passport-local 一起使用,尽管它没有很好的文档记录。我最终使用jsonwebtoken 并使用passport-local 处理用户身份验证,然后提供了一个自定义回调来分配网络令牌。对于其他人,我相信有一个 passport-jwt 包可以简化事情。
【解决方案3】:

对于 REST,我建议您使用带有 HTTPS 的 HTTP Basic/Digest 身份验证,您可以使用 http-auth 来实现:

// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
    realm: "Simon Area.",
    file: __dirname + "/../data/users.htpasswd" // gevorg:gpass, Sarah:testpass ...
});

// Application setup.
var app = express();

// Setup strategy.
var passport = require('passport');
passport.use(auth.passport(basic));

// Setup route.
app.get('/', passport.authenticate('http', { session: false }), function(req, res) {
    res.end("Welcome to private area - " + req.user + "!");
});

或者你可以不使用passport:

// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
    realm: "Simon Area.",
    file: __dirname + "/../data/users.htpasswd" // gevorg:gpass, Sarah:testpass ...
});

// Application setup.
var app = express();
app.use(auth.connect(basic));

// Setup route.
app.get('/', function(req, res){
  res.send("Hello from express - " + req.user + "!");
});

【讨论】:

    猜你喜欢
    • 2013-09-07
    • 1970-01-01
    • 2016-11-10
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多