波卡的验证人节点_轻松节点身份验证:设置和本地

波卡的验证人节点

here. 在这里阅读更多。

Edit 11/18/2017: Updated to reflect Facebook API changes. Updating dependencies in package.json

编辑11/18/2017:已更新以反映Facebook API的更改。 更新package.json中的依赖项

Authentication and logins in Node can be a complicated thing. Actually logging in for any application can be a pain. This article series will deal with authenticating in your Node application using the package Passport.

Node中的身份验证和登录可能很复杂。 实际登录任何应用程序都可能会很痛苦。 本系列文章将讨论使用Passport软件包在Node应用程序中进行身份验证。

我们将要建立的: (What we'll be building:)

We will build an application that will have:

我们将构建一个具有以下功能的应用程序:

  • Local account logins and signups (using passport-local)

    本地帐户登录和注册(使用本地护照
  • Facebook logins and registration (using passport-facebook)

    Facebook登录和注册(使用passport-facebook
  • Twitter logins and registration (using passport-twitter)

    Twitter登录和注册(使用通行证
  • Google+ logins and registration (using oauth with passport-google-oauth)

    Google+登录和注册(将oauth与password-google-oauth结合使用
  • Require login for certain routes/sections of your application

    需要登录您的应用程序的某些路线/部分
  • Creating a password hash for local accounts (using bcrypt-nodejs)

    为本地帐户创建密码哈希(使用bcrypt-nodejs
  • Displaying error messages (using flash with connect-flash. required since express 3.x)

    显示错误消息(自Express 3.x起需要使用带有connect-flash的Flash
  • Linking all social accounts under one user account

    关联一个用户帐户下的所有社交帐户
  • Allowing a user to unlink a specific social account

    允许用户取消关联特定的社交帐户

教程系列 (The Tutorial Series)

We'll release this entire gigantic series over 5 different tutorials. They are:

我们将在5个不同的教程中发布整个庞大的系列。 他们是:

  1. Getting Set up and Local Authentication

    设置和本地身份验证
  2. Facebook Authentication

    Facebook认证
  3. Twitter Authentication

    Twitter认证
  4. Google Authentication

    Google认证
  5. Linking all accounts together

    将所有帐户关联在一起

Enough chit chat. Let's dive right into a completely blank Node application and build our entire application from scratch.

闲聊。 让我们直接进入一个完全空白的Node应用程序,并从头开始构建整个应用程序。

Here's what we'll be building:

这是我们将要构建的:

node-authentication
And after a user has logged in with all their credentials:

在用户使用所有凭据登录后:

node-authentication-profile
For this article, we'll be focusing on setup and only local logins and registrations/signups. Since this is the first article and also deals with setting up our application, it will probably be one of the longer ones if not the longest. Sit tight for the duration of your flight.

对于本文,我们将专注于设置,仅关注本地登录和注册/注册。 由于这是第一篇文章,同时也涉及如何设置我们的应用程序,因此即使不是最长的文章也可能是更长的文章之一。 在飞行过程中请坐好。

设置我们的应用程序 (Setting Up Our Application)

To set up our base Node application, we'll need a few things. We'll set up our npm packages, node application, configuration files, models, and routes.

要设置基本的Node应用程序,我们需要做一些事情。 我们将设置npm软件包节点应用程序配置文件模型路由

应用结构 ( Application Structure )

- app
    ------ models
    ---------- user.js  <!-- our user model -->
    ------ routes.js    <!-- all the routes for our application -->
    - config
    ------ auth.js      <!-- will hold all our client secret keys (facebook, twitter, google) -->
    ------ database.js  <!-- will hold our database connection settings -->
    ------ passport.js  <!-- configuring the strategies for passport -->
    - views
    ------ index.ejs    <!-- show our home page with login links -->
    ------ login.ejs    <!-- show our login form -->
    ------ signup.ejs   <!-- show our signup form -->
    ------ profile.ejs  <!-- after a user logs in, they will see their profile -->
    - package.json      <!-- handle our npm packages -->
    - server.js         <!-- setup our application -->

Go ahead and create all those files and folders and we'll fill them in as we go along.

继续创建所有这些文件和文件夹,然后继续进行操作。

软件包package.json ( Packages package.json )

We are going to install all the packages needed for the entire tutorial series. This means we'll install all the packages needed for passport local, facebook, twitter, google, and the other things we need. It's all commented out so you know what each does.

我们将安装整个教程系列所需的所有软件包。 这意味着我们将安装本地护照,facebook,twitter,google和其他所需的护照所需的所有软件包。 全部注释掉了,所以您知道每个功能。

// package.json

{
  "name": "node-authentication",
  "main": "server.js",
  "dependencies" : {
    "express" : "~4.14.0",           
    "ejs" : "~2.5.2",               
    "mongoose" : "~4.13.1",          
    "passport" : "~0.3.2",         
    "passport-local" : "~1.0.0",    
    "passport-facebook" : "~2.1.1", 
    "passport-twitter" : "~1.0.4",  
    "passport-google-oauth" : "~1.0.0",
    "connect-flash" : "~0.1.1",     
    "bcrypt-nodejs" : "latest",

    "morgan": "~1.7.0",
    "body-parser": "~1.15.2",
    "cookie-parser": "~1.4.3",
    "method-override": "~2.3.6",
    "express-session": "~1.14.1"   
  }
}

Most of these are pretty self-explanatory.

其中大多数都是不言自明的。

  • Express is the framework.

    Express是框架。
  • Ejs is the templating engine.

    Ejs是模板引擎。
  • Mongoose is object modeling for our MongoDB database.

    Mongoose是我们MongoDB数据库的对象建模。
  • Passport stuff will help us authenticating with different methods.

    护照资料将帮助我们使用不同的方法进行身份验证。
  • Connect-flash allows for passing session flashdata messages.

    Connect-flash允许传递会话flashdata消息。
  • Bcrypt-nodejs gives us the ability to hash the password.

    Bcrypt-nodejs使我们能够对密码进行哈希处理。

I use bcrypt-nodejs instead of bcrypt since it is easier to set up in windows. For more information on the newer ExpressJS 4.0 dependencies (morgan, body-parser, cookie-parser, method-override, express-session), see this article on

我使用bcrypt-nodejs而不是bcrypt,因为在Windows中更容易设置。 有关较新的ExpressJS 4.0依赖项(morgan,body解析器,cookie解析器,方法重写,express-session)的详细信息,请参阅本文。

ExpressJS 4.0. Now that we have all of our dependencies ready to go, let's go ahead and install them:

ExpressJS 4.0 。 现在我们已经准备好所有依赖项,让我们继续安装它们:

npm install With all of our packages ready to go, let's set up our application in server.js.

npm install在准备好所有软件包之后,让我们在server.js设置应用程序。

应用程序设置server.js ( Application Setup server.js )

Let's make all our packages work together nicely. Our goal is to set up this file and try to have it bootstrap our entire application. We'd like to not go back into this file if it can be helped. This file will be the glue for our entire application.

让我们所有的程序包都能很好地协同工作。 我们的目标是设置此文件,并尝试使其自举整个应用程序。 如果可以提供帮助,我们希望不要再返回该文件。 该文件将成为我们整个应用程序的粘合剂。

// server.js

// set up ======================================================================
// get all the tools we need
var express  = require('express');
var app      = express();
var port     = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash    = require('connect-flash');

var morgan       = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser   = require('body-parser');
var session      = require('express-session');

var configDB = require('./config/database.js');

// configuration ===============================================================
mongoose.connect(configDB.url); // connect to our database

// require('./config/passport')(passport); // pass passport for configuration

// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser()); // get information from html forms

app.set('view engine', 'ejs'); // set up ejs for templating

// required for passport
app.use(session({ secret: 'ilovescotchscotchyscotchscotch' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session

// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport

// launch ======================================================================
app.listen(port);
console.log('The magic happens on port ' + port);

We are going to comment out our passport configuration for now. We'll uncomment it after we create that config/passport.js file.

现在,我们将注释掉我们的护照配置。 创建该config/passport.js文件后,我们将取消对其的注释。

The path of our passport object is important to note here. We will create it at the very beginning of the file with var passport = require('passport');. Then we pass it into our config/passport.js file for it to be configured. Then we pass it to the app/routes.js file for it to be used in our routes.

我们在此注意护照对象的路径很重要。 我们将在文件的开头创建它,使用var passport = require('passport'); 。 然后,将其传递到config/passport.js文件中进行配置。 然后,将其传递到app/routes.js文件,以便在路由中使用。

Now with this file, we have our application listening on port 8080. All we have to do to start up our server is:

现在有了这个文件,我们的应用程序将监听端口8080 。 要启动服务器,我们要做的就是:

node server.js Then when we visit http://localhost:8080 we will see our application. (Not really right this moment since we have some more set up to do)

node server.js然后,当我们访问http:// localhost:8080时 ,将看到我们的应用程序。 (由于我们还有很多工作要做,所以此刻不正确)

Auto Refreshing: By default, node doesn't automatically refresh our server every time we change files. To do that we'll use 自动刷新:默认情况下,节点不会在每次更改文件时自动刷新服务器。 为此,我们将使用 nodemon. Just install with: nodemon 。 只需使用以下命令安装: npm install -g nodemon and use with: npm install -g nodemon然后使用: nodemon server.js. nodemon server.js

Now this won't do much for our application since we don't have our database configuration, routes, user model, or passport configuration set up. Let's do the database and routes now.

现在,这对我们的应用程序没有多大作用,因为我们没有设置数据库配置路线用户模型通行证配置 。 现在开始数据库和路由。

数据库配置config / database.js ( Database Config config/database.js )

We already are calling this file in server.js. Now we just have to set it up.

我们已经在server.js中调用了该文件。 现在我们只需要设置它。

// config/database.js
module.exports = {

    'url' : 'your-settings-here' // looks like mongodb://<user>:<pass>@mongo.onmodulus.net:27017/Mikha4ot

};

Fill this in with your own database. If you don't have a MongoDB database lying around, I would suggest going to Modulus.io and grabbing one. Once you sign up (and you get a $15 credit for signing up), you can create your database, grab its connection url, and place it in this file.

用您自己的数据库填写。 如果您周围没有MongoDB数据库,建议您转到Modulus.io并抓住其中一个。 一旦您注册(并获得15美元的注册信用),就可以创建数据库,获取其连接URL并将其放置在此文件中。

You can also install MongoDB locally and use a local database. You can find instructions here: An Introduction to MongoDB.

您还可以在本地安装MongoDB并使用本地数据库。 您可以在此处找到说明: MongoDB简介

路由app / routes.js ( Routes app/routes.js )

We will keep our routes simple for now. We will have the following routes:

我们暂时将使路线保持简单。 我们将有以下路线:

  • Home Page (/)

    主页 (/)
  • Login Page (/login)

    登录页面(/登录)
  • Signup Page (/signup)

    注册页面(/注册)
  • Handle the POST for both login

    处理两次登录的POST
  • Handle the POST for both signup

    处理两个注册的POST
  • Profile Page (after logged in)

    个人资料页面(登录后)
// app/routes.js
module.exports = function(app, passport) {

    // =====================================
    // HOME PAGE (with login links) ========
    // =====================================
    app.get('/', function(req, res) {
        res.render('index.ejs'); // load the index.ejs file
    });

    // =====================================
    // LOGIN ===============================
    // =====================================
    // show the login form
    app.get('/login', function(req, res) {

        // render the page and pass in any flash data if it exists
        res.render('login.ejs', { message: req.flash('loginMessage') }); 
    });

    // process the login form
    // app.post('/login', do all our passport stuff here);

    // =====================================
    // SIGNUP ==============================
    // =====================================
    // show the signup form
    app.get('/signup', function(req, res) {

        // render the page and pass in any flash data if it exists
        res.render('signup.ejs', { message: req.flash('signupMessage') });
    });

    // process the signup form
    // app.post('/signup', do all our passport stuff here);

    // =====================================
    // PROFILE SECTION =====================
    // =====================================
    // we will want this protected so you have to be logged in to visit
    // we will use route middleware to verify this (the isLoggedIn function)
    app.get('/profile', isLoggedIn, function(req, res) {
        res.render('profile.ejs', {
            user : req.user // get the user out of session and pass to template
        });
    });

    // =====================================
    // LOGOUT ==============================
    // =====================================
    app.get('/logout', function(req, res) {
        req.logout();
        res.redirect('/');
    });
};

// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {

    // if user is authenticated in the session, carry on 
    if (req.isAuthenticated())
        return next();

    // if they aren't redirect them to the home page
    res.redirect('/');
}

app.post: For now, we will comment out the routes for handling the form POST. We do this since passport isn't set up yet.

app.post :目前,我们将注释掉处理POST表单的路由。 因为尚未设置护照,所以我们这样做。

req.flash: This is the connect-flash way of getting flashdata in the session. We will create the loginMessage inside our passport configuration.

req.flash :这是在会话中获取flashdata的连接Flash方法。 我们将在我们的护照配置中创建loginMessage

isLoggedIn: Using route middleware, we can protect the profile section route. A user has to be logged in to access that route. Using the isLoggedIn function, we will kick a user back to the home page if they try to access http://localhost:8080/profile and they are not logged in.

isLoggedIn :使用路由中间件 ,我们可以保护配置文件部分的路由。 用户必须登录才能访问该路由。 使用isLoggedIn函数,如果用户尝试访问http://localhost:8080/profile并且未登录 ,我们会将其踢回到主页。

Logout: We will handle logout by using req.logout() provided by passport. After logging out, redirect the user to the home page.

注销 :我们将使用护照提供的req.logout()处理注销。 注销后,将用户重定向到主页。

With our server running, we can visit our application in our browser at http://localhost:8080. Once again, we won't see much since we haven't made our views. Let's go do that now. (We're almost to the authentication stuff, I promise).

随着服务器运行,我们可以在浏览器中访问我们的应用程序, 网址http:// localhost:8080 。 再一次,因为我们没有发表意见,所以我们看不到什么。 我们现在就去做。 (我保证,我们几乎要进行身份验证了)。

查看views / index.ejs,views / login.ejs,views / signup.ejs ( Views views/index.ejs, views/login.ejs, views/signup.ejs )

Here we'll define our views for our home page, login page, and signup/registration page.

在这里,我们将为主页登录页面注册/注册页面定义视图。

主页views / index.ejs (Home Page views/index.ejs)

Our home page will just show links to all our forms of authentication.

我们的主页将仅显示指向我们所有身份验证形式的链接。

<!-- views/index.ejs -->
<!doctype html>
<html>
<head>
    <title>Node Authentication</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
    <style>
        body        { padding-top:80px; }
    </style>
</head>
<body>
<div class="container">

    <div class="jumbotron text-center">
        <h1><span class="fa fa-lock"></span> Node Authentication</h1>

        <p>Login or Register with:</p>

        <a href="/login" class="btn btn-default"><span class="fa fa-user"></span> Local Login</a>
        <a href="/signup" class="btn btn-default"><span class="fa fa-user"></span> Local Signup</a>
    </div>

</div>
</body>
</html>

Now if we visit our app in our browser, we'll have a site that looks like this:

现在,如果我们在浏览器中访问我们的应用程序,我们将拥有一个看起来像这样的网站:

node-authentication-local
Here are the views for our login and signup pages also.

这也是我们的登录和注册页面的视图。

登录表单views / login.ejs (Login Form views/login.ejs)

<!-- views/login.ejs -->
<!doctype html>
<html>
<head>
    <title>Node Authentication</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
    <style>
        body        { padding-top:80px; }
    </style>
</head>
<body>
<div class="container">

<div class="col-sm-6 col-sm-offset-3">

    <h1><span class="fa fa-sign-in"></span> Login</h1>

    <!-- show any messages that come back with authentication -->
    <% if (message.length > 0) { %>
        <div class="alert alert-danger"><%= message %></div>
    <% } %>

    <!-- LOGIN FORM -->
    <form action="/login" method="post">
        <div class="form-group">
            <label>Email</label>
            <input type="text" class="form-control" name="email">
        </div>
        <div class="form-group">
            <label>Password</label>
            <input type="password" class="form-control" name="password">
        </div>

        <button type="submit" class="btn btn-warning btn-lg">Login</button>
    </form>

    <hr>

    <p>Need an account? <a href="/signup">Signup</a></p>
    <p>Or go <a href="/">home</a>.</p>

</div>

</div>
</body>
</html>

node-auth-local-login

注册表单views / signup.ejs (Signup Form views/signup.ejs)

<!-- views/signup.ejs -->
<!doctype html>
<html>
<head>
    <title>Node Authentication</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
    <style>
        body        { padding-top:80px; }
    </style>
</head>
<body>
<div class="container">

<div class="col-sm-6 col-sm-offset-3">

    <h1><span class="fa fa-sign-in"></span> Signup</h1>

    <!-- show any messages that come back with authentication -->
    <% if (message.length > 0) { %>
        <div class="alert alert-danger"><%= message %></div>
    <% } %>

    <!-- LOGIN FORM -->
    <form action="/signup" method="post">
        <div class="form-group">
            <label>Email</label>
            <input type="text" class="form-control" name="email">
        </div>
        <div class="form-group">
            <label>Password</label>
            <input type="password" class="form-control" name="password">
        </div>

        <button type="submit" class="btn btn-warning btn-lg">Signup</button>
    </form>

    <hr>

    <p>Already have an account? <a href="/login">Login</a></p>
    <p>Or go <a href="/">home</a>.</p>

</div>

</div>
</body>
</html>

node-auth-local-signup

在本地使用Passport进行身份验证 (Authenticating With Passport Locally)

Finally! We have finally set up our application and have gotten to the authentication part. Don't worry. The rest of the authentication articles in this tutorial series will use the same base so we won't have to set up our application again.

最后! 我们终于建立了我们的应用程序,并进入了身份验证部分。 不用担心 本教程系列中的其余身份验证文章将使用相同的基础,因此我们无需再次设置应用程序。

So far we have installed our packages, set up our application, connected to our database, created our routes, and created our views.

到目前为止,我们已经安装了软件包设置了应用程序连接到数据库创建了路线创建了视图

Now we will create our user model, configure passport for local authentication, and use our configured passport to process our login/signup forms.

现在,我们将创建用户模型配置用于本地身份验证的通行证 ,并使用配置的通行证来处理我们的登录/注册表单

用户模型 ( User Model )

We will create our user model for the entire tutorial series. Our user will have the ability to be linked to multiple social accounts and to a local account. For local accounts, we will be keeping email and password. For the social accounts, we will be keeping their id, token, and some user information.

我们将为整个教程系列创建用户模型。 我们的用户将能够链接到多个社交帐户和一个本地帐户。 对于本地帐户,我们将保留电子邮件密码 。 对于社交帐户,我们将保留其idtoken和一些用户信息。

You can change these fields out to be whatever you want. You can authenticate locally using username and password (passport-local actually uses username by default but we'll change that to email).

您可以将这些字段更改为任意字段。 您可以使用用户名和密码在本地进行身份验证(默认情况下,passport-local实际上使用用户名,但我们会将其更改为电子邮件)。

// app/models/user.js
// load the things we need
var mongoose = require('mongoose');
var bcrypt   = require('bcrypt-nodejs');

// define the schema for our user model
var userSchema = mongoose.Schema({

    local            : {
        email        : String,
        password     : String,
    },
    facebook         : {
        id           : String,
        token        : String,
        name         : String,
        email        : String
    },
    twitter          : {
        id           : String,
        token        : String,
        displayName  : String,
        username     : String
    },
    google           : {
        id           : String,
        token        : String,
        email        : String,
        name         : String
    }

});

// methods ======================
// generating a hash
userSchema.methods.generateHash = function(password) {
    return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};

// checking if password is valid
userSchema.methods.validPassword = function(password) {
    return bcrypt.compareSync(password, this.local.password);
};

// create the model for users and expose it to our app
module.exports = mongoose.model('User', userSchema);

Our model is done. We will be hashing our password within our user model before it saves to the database. This means we don't have to deal with generating the hash ourselves. It is all handled nicely and neatly inside our user model.

我们的模型完成了。 在将密码保存到数据库之前,我们将在用户模型中对密码进行哈希处理。 这意味着我们不必自己处理散列。 在我们的用户模型中,一切都得到了很好的处理。

Let's move onto the important stuff of this article: authenticating locally!

让我们继续本文的重要内容: 本地认证

为本地帐户配置护照 (Configuring Passport for Local Accounts)

All the configuration for passport will be handled in config/passport.js. We want to keep this code in its own file away from our other main files like routes or the server file. I have seen some implementations where passport will be configured in random places. I believe having it in this config file will keep your overall application clean and concise.

护照的所有配置将在config/passport.js处理。 我们希望将此代码保留在其自己的文件中,远离诸如路由或服务器文件之类的其他主文件。 我已经看到一些将在任意位置配置护照的实现。 我相信在此配置文件中拥有该文件将使您的整个应用程序简洁明了。

So far, we created our passport object in server.js, and then we pass it to our config/passport.js file. This is where we configure our Strategy for local, facebook, twitter, and google. This is also the file where we will create the serializeUser and deserializeUser functions to store our user in session.

到目前为止,我们在server.js创建了护照对象,然后将其传递到config/passport.js文件。 这是我们为本地,facebook,twitter和google配置策略的地方。 这也是我们将在其中创建serializeUserdeserializeUser函数以在会话中存储我们的用户的文件。

I would highly recommend going to read the passport docs to understand more about how the package works.

我强烈建议您阅读护照文档,以进一步了解包裹的工作原理。

处理注册/注册 ( Handling Signup/Registration )

We will be handling login and signup in config/passport.js. Let's look at signup first.

我们将在config/passport.js处理登录和注册。 让我们先来看一下注册。

// config/passport.js

// load all the things we need
var LocalStrategy   = require('passport-local').Strategy;

// load up the user model
var User            = require('../app/models/user');

// expose this function to our app using module.exports
module.exports = function(passport) {

    // =========================================================================
    // passport session setup ==================================================
    // =========================================================================
    // required for persistent login sessions
    // passport needs ability to serialize and unserialize users out of session

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

    // =========================================================================
    // LOCAL SIGNUP ============================================================
    // =========================================================================
    // we are using named strategies since we have one for login and one for signup
    // by default, if there was no name, it would just be called 'local'

    passport.use('local-signup', new LocalStrategy({
        // by default, local strategy uses username and password, we will override with email
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true // allows us to pass back the entire request to the callback
    },
    function(req, email, password, done) {

        // asynchronous
        // User.findOne wont fire unless data is sent back
        process.nextTick(function() {

        // find a user whose email is the same as the forms email
        // we are checking to see if the user trying to login already exists
        User.findOne({ 'local.email' :  email }, function(err, user) {
            // if there are any errors, return the error
            if (err)
                return done(err);

            // check to see if theres already a user with that email
            if (user) {
                return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
            } else {

                // if there is no user with that email
                // create the user
                var newUser            = new User();

                // set the user's local credentials
                newUser.local.email    = email;
                newUser.local.password = newUser.generateHash(password);

                // save the user
                newUser.save(function(err) {
                    if (err)
                        throw err;
                    return done(null, newUser);
                });
            }

        });    

        });

    }));

};

We have now provided a strategy to passport called local-signup. We will use this strategy to process our signup form. Let's open up our app/routes.js and handle the POST for our signup form.

现在,我们为护照提供了一种称为local-signup的策略。 我们将使用此策略来处理我们的注册表单。 让我们打开app/routes.js并处理我们的注册表单的POST。

// app/routes.js
...

    // process the signup form
    app.post('/signup', passport.authenticate('local-signup', {
        successRedirect : '/profile', // redirect to the secure profile section
        failureRedirect : '/signup', // redirect back to the signup page if there is an error
        failureFlash : true // allow flash messages
    }));

...

That's all the code we need for the route. All of the heavy duty stuff lives inside of config/passport.js. All we have to set here is where our failures and successes get redirected. Super clean.

这就是我们需要的所有代码。 所有繁重的工作都位于config/passport.js内部。 我们在这里要做的就是重定向我们的失败和成功。 超级干净。

There is also much more you can do with this. Instead of specifying a successRedirect, you could use a callback and take more control over how your application works. Here is a great stackoverflow answer on error handling. It explains how to use done() and how to be more specific with your handling of a route.

您还可以做更多的事情。 除了指定一个successRedirect ,您还可以使用回调并更好地控制应用程序的工作方式。 这是错误处理的一个很好的stackoverflow答案 。 它说明了如何使用done()以及如何更具体地处理路由。

测试注册 (Testing Signup)

With our passport config finally laid out, we can uncomment that line in our server.js. This will load our config and then we can use our signup form.

最终完成我们的护照配置后,我们可以在server.js取消注释该行。 这将加载我们的配置,然后我们可以使用我们的注册表单。

// server.js
...

    // uncomment this line
    require('./config/passport')(passport); // pass passport for configuration

...

Now that we have passport, our routes, and our redirects in place, let's go ahead and test our signup form. In your browser, go to http://localhost:8080/signup and fill out your form.

现在我们已经有了护照,路线和重定向,让我们继续测试我们的注册表单。 在浏览器中,转到http:// localhost:8080 / signup并填写表格。

If all goes according to plan, you should be logged in, your user saved in the session, and you are redirected to the /profile page (the profile page will show nothing right now since we haven't defined that view).

如果一切都按计划进行,则应该登录 ,将用户保存在会话中 ,然后您将重定向到/ profile页面 (由于我们尚未定义该视图,因此profile页面现在将不显示任何内容)。

If we look in our database, we'll also see our user sitting there cozily with all the credentials we created for him.

如果我们查看数据库,还将看到我们的用户舒适地坐在那里,并为他创建了所有凭据。

node-user-in-database

Exploring Your Database: I use 探索您的数据库 :我使用 Robomongo to see what's in my database. Just download it and connect to your database to see your new users after they signup! Robomongo来查看数据库中的内容。 只需下载它并连接到您的数据库,即可在新用户注册后查看他们!

With users able to sign up, let's give them a way to login.

随着用户能够注册,让我们为他们提供一种登录方式。

登录 ( Login )

This will be very similar to the signup strategy. We'll add the strategy to our config/passport.js and the route in app/routes.js.

这将与注册策略非常相似。 我们将策略添加到config/passport.js ,并将路由添加到app/routes.js

// config/passport.js

...

    // =========================================================================
    // LOCAL LOGIN =============================================================
    // =========================================================================
    // we are using named strategies since we have one for login and one for signup
    // by default, if there was no name, it would just be called 'local'

    passport.use('local-login', new LocalStrategy({
        // by default, local strategy uses username and password, we will override with email
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true // allows us to pass back the entire request to the callback
    },
    function(req, email, password, done) { // callback with email and password from our form

        // find a user whose email is the same as the forms email
        // we are checking to see if the user trying to login already exists
        User.findOne({ 'local.email' :  email }, function(err, user) {
            // if there are any errors, return the error before anything else
            if (err)
                return done(err);

            // if no user is found, return the message
            if (!user)
                return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash

            // if the user is found but the password is wrong
            if (!user.validPassword(password))
                return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata

            // all is well, return successful user
            return done(null, user);
        });

    }));

};

We have now provided a strategy to passport called local-login. We will use this strategy to process our login form. We can check if a user exists, if the password is wrong, and set flash data to show error messages. Let's open up our app/routes.js and handle the POST for our login form.

现在,我们为护照提供了一种名为local-login的策略。 我们将使用此策略来处理我们的登录表单。 我们可以检查用户是否存在,密码是否错误,并设置Flash数据以显示错误消息。 让我们打开app/routes.js并处理登录表单的POST。

// app/routes.js
...

    // process the login form
    app.post('/login', passport.authenticate('local-login', {
        successRedirect : '/profile', // redirect to the secure profile section
        failureRedirect : '/login', // redirect back to the signup page if there is an error
        failureFlash : true // allow flash messages
    }));

...

If you try to login with a user email that doesn't exist in our database, you will see the error. Same goes for if your password is wrong.

如果您尝试使用数据库中不存在的用户电子邮件登录,则会看到该错误。 如果您的密码错误,同样适用。

node-auth-login-error

显示用户和安全配置文件页面views / profile.ejs ( Displaying User and Secure Profile Page views/profile.ejs )

Now we have functional signup and login forms. If a user is successful in authenticating they will be redirected to the profile page. If they are not successful, they will go home. The last thing we need to do is make our profile page so that those that are lucky enough to signup (all of us?) will have an exclusive place of our site all to themselves.

现在我们有了功能性的注册和登录表单。 如果用户认证成功,他们将被重定向到个人资料页面。 如果他们不成功,他们将回家。 我们需要做的最后一件事是创建个人资料页面,以便那些有幸注册的人(我们所有人?)将自己拥有我们网站的专有位置。

<!-- views/profile.ejs -->
<!doctype html>
<html>
<head>
    <title>Node Authentication</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
    <style>
        body        { padding-top:80px; word-wrap:break-word; }
    </style>
</head>
<body>
<div class="container">

    <div class="page-header text-center">
        <h1><span class="fa fa-anchor"></span> Profile Page</h1>
        <a href="/logout" class="btn btn-default btn-sm">Logout</a>
    </div>

    <div class="row">

        <!-- LOCAL INFORMATION -->
        <div class="col-sm-6">
            <div class="well">
                <h3><span class="fa fa-user"></span> Local</h3>

                    <p>
                        <strong>id</strong>: <%= user._id %><br>
                        <strong>email</strong>: <%= user.local.email %><br>
                        <strong>password</strong>: <%= user.local.password %>
                    </p>

            </div>
        </div>

    </div>

</div>
</body>
</html>

After a user logs in, they can see all their information. It is grabbed from the session and passed to our view in the app/routes.js file. We will also provide a link to logout.

用户登录后,他们可以查看其所有信息。 它是从会话中获取的,并传递到app/routes.js文件中的视图。 我们还将提供注销链接。

node-auth-local-profile-page

结论 ( Conclusion )

There you have it! We've built a brand new application from scratch and have the ability to let users signup/register and login. We even have support for flash messages, hashing passwords, and requiring login for some sections of our site using route middleware.

你有它! 我们从头开始构建了一个全新的应用程序,并且能够让用户注册/注册和登录。 我们甚至支持Flash消息,哈希密码,并要求使用路由中间件登录我们网站的某些部分。

Coming up next we'll be looking at how to take this same structure, and use passport to authenticate with Facebook, Twitter, and Google. After that we'll look at how we can get all these thing working together in the same application. Users will be able to login with one type of account, and then link their other accounts.

接下来,我们将研究如何采用相同的结构,并使用护照对Facebook,Twitter和Google进行身份验证。 之后,我们将研究如何在同一个应用程序中使所有这些东西一起工作。 用户将能够使用一种类型的帐户登录,然后链接其其他帐户。

As always, if you see any ways to improve this or need any clarification, sound off in the comments and we'll respond pretty close to immediately... pretty close.

与往常一样,如果您发现任何改善此问题的方法或需要任何澄清,请在评论中略过一声,我们将立即接近做出回应……非常接近。

Edit #1: Changed password hashing to be handled inside user model and asynchronously. 编辑#1 :更改密码哈希以在用户模型内部并异步处理。 Edit #2: Changed password hashing to be explicitly called. Helps with future tutorials. 编辑#2 :更改了要显式调用的密码哈希。 帮助将来的教程。

翻译自: https://scotch.io/tutorials/easy-node-authentication-setup-and-local

波卡的验证人节点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值