Mean full stack development user authentication

Source: Internet
Author: User
Tags findone

Soaring_tiger
http://blog.csdn.net/Soaring_Tiger/article/details/51418209
This article will cover the following (read this article requires a certain express, mongoose basis):

  1. Add user authentication to mean full stack development
  2. Manage user authentication with the Passport module in Express
  3. Generating a JSON Web Tokens (JWT) in exrpess
  4. Implement user Registration and login
  5. Use local storage to manage user session in angular
1.1 How to implement user authentication in mean development?

For a single-page program like angular (SPA), user authentication seems like a hassle, because all the (front-end) programs are sent to the browser, so how to hide what you want to hide is a problem.

1.1.1 Let's take a look at how traditional service-based programs are implemented.

If you are more familiar with traditional server-based web development (such as PHP, the best in the world), you may be confused about how a single page application (SPA) can implement user authentication.
The traditional user authentication process for Web development based on the service side is typically this:
(1) The user enters the user name and password on the form and submits it to the server;
(2) The program on the server verifies the user name and password and the correct permissions through the database;
(3) If the verification is successful, the server marks the user's session and tells the user that he has logged in successfully;
(4) When the user browses the page, the browser will send the cookie to the server, the server will verify the user's session and browse permissions, and return the page to the user.
So, like mean full stack development mode and how to do it?

1.1.2 mean full stack user authentication implementation method

Mean full stack user authentication is faced with two problems:

    1. The API implemented via Express is stateless, that is, the concept of no user session.
    2. The programming logic of the single-page program (SPA) has been transferred to the browser, so you cannot restrict these already in the browser-side code.

The logical solution is to maintain a certain user session state on the browser side, so that the front-end program determines what can be displayed to the user, what cannot be displayed to the user, which differs from the way the server controls it, but this is the main change.
A good and safe approach is to use a JSON Web Token (JWT) to store user data on the client. For the details of JWT we'll talk about it later, and now you just have to know that it's an encrypted JSON object.

Manage Login Processes

Figure 5
Figure 5 illustrates a login process: (1) The user submits their authentication information to the server via the API, (2) The server verifies the user's identity information through the database, (3) The server returns a token to the client, (4) The client token is saved and is used the next time it is needed.
In fact, the entire process is similar to the traditional server implementation scheme, but the user session exists on the client.

rely on user authentication information to show content

Figure 6
6, during the user session, when the user wants to see the new page, the front-end program can determine whether the user has permission to browse based on the information that is kept in the JWT.
Unlike traditional implementations, unless the user needs to get the information from the database through the API, the mean server does not care what the user is looking at.

Secure Call API

If some parts of the application are limited to a particular user, then for a stateless API, every call to the API needs to know the invocation permissions, and this is where the JWT comes in handy. As shown in 7, the client sends a JWT when invoking an API endpoint that requires authentication, and the server authenticates the user's request by decoding the JWT.
Figure 7

OK, the above section introduces the basic concepts, we already know what to do in general. Let's step through the process.

2. Creating a user Data model for MongoDB (users Schema)

Usernames and passwords are usually stored in the database, and we need to build a model through mongoose in mean full stack development. The special need to remind is: password in the database must not be saved in clear text! , because it creates a huge security hole.

2.1 One-way password encryption: hash + salt

There is one way to improve the security of your password: one-way encryption of passwords. One-way encryption prevents anyone from decrypting, and it's very easy to verify the password. When the user logs in, the program can encrypt the password and compare the values that are already stored.
Of course, if just simple encryption is not enough, because if a lot of people use the same password (for example: 123456), then the encrypted string will be identical, and hackers can easily find the weak password encryption mode.
This time you need to rely on "salt" to help, so-called "salt" is a user password is encrypted for each user randomly generated string, and the password mixed with the result is "hash", 8 is shown.
Figure 8
"Salt" and "hash" are stored together in the database, not just a "password" field, through the above process, all the "hash" is unique, so it is good to protect the password.

2.2 Creating a Mongoose Model

The Userschema we created contains
Several fields, such as user name, e-mail (email), hash (hash), salt, and so on. Where email is required and is the only field, name is the necessary field.

var=require‘mongoose‘ );var=new mongoose.Schema({  email: {?    typeString,    true,    true}, name: {    typeString,    true  },  String,  String});
2.3 Setting the encryption path using the Mongoose method

Mongoose allows the user to add a custom method to the schema, such as the "SetPassword" method in the following code

var User = mongoose.model(‘User‘);     //实例化用户模型varnew User();                 //创建新用户"User’s name";             //设置用户名  "[email protected]";       //设置用户邮箱user.setPassword("myPassword");        //调用自定义setPassword方法设置用户密码user.save();                           //保存用户                        
Let's take a look at how to add a method to the Mongoose schema

After the schema is defined, we can add a method to the schema before the data model is compiled. The following code example adds a SetPassword method to Userschema:

function(password){  this.salt = SALT_VALUE;  this.hash = HASH_VALUE;};

For JavaScript, "This" actually refers to the model itself in mongoose, which in this case is Userschema.
Before we save the user profile, we must also generate a random "salt" and a "hash" after encrypting the password. Fortunately, node. JS has a native library that Vikings this: crypto.

Using Crypto for encryption

Crypto as the name implies is encryption, it provides a series of methods for processing data encryption; Let's take a look at these two:

    • randombytes--generates a sufficiently "robust" string as "salt"
    • pbkdf2sync--constructs a "hash" by means of a password (password) and salts (salt); PBKDF2 is the abbreviation for password-based key derivation function 2, which is an industry standard for encryption.

First, we need to introduce the Crypto library at the beginning of the file

varrequire‘mongoose‘ );varrequire(‘crypto‘);

Then, our SetPassword function to update, the resulting "salt" is a 16-bit string, and then use "salt" to encrypt the password "hash":

userSchema.methods.setPassword =function(password){this.salt = crypto.randomBytes(16).toString(‘hex‘thisthis1000,64).toString(‘hex‘);};

Now, the password entered by the user is securely encrypted, the original password is not saved anywhere (including memory), that is, no one can get the original password.

2.4 Verifying the submitted password

After encrypting the user password, another thing to do is to verify the user's password the next time the user logs in, we can write a simple mongoose method to do this:

function(password) {varthis100064).toString(‘hex‘returnthis.hash === hash;};

The code above is a "hash" of the password entered by the user, followed by a comparison with the original "hash". How? The code is easy to implement. ^_^

So the last thing we need to do next is generate the JSON Web Token (JWT).

2.5 Generating the JSON Web Token

The purpose of the so-called JWT (pronounced "jot") is to pass data between the server and our client spa programs. JWT can of course also be used for user authentication between the server and the client.
Let's look at the composition of the JWT:

The three components of a JWT

Let's look at a real JWT example:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI2xtZXMiLCJleHAiOjE0MzUwNDA0MTgsImlhdCI6MTQzNDQzNTYxOH0.GD7UrfnLk295rwvIrCikbk AKctFFoRCHotLYZwZpdlE

You look dizzy, don't you? In fact, if you have good eyesight, you will find that this super long string is actually two "." Divided into three parts, the three parts are:

    • Header--A JSON object that is encoded and contains a type and hash algorithm;
    • Valid data (Payload)--a JSON object encoded with token information;
    • Signature (Signature)--
      A "hash" that encrypts the header and payload with a key on the server.

Note: The first two sections are not encrypted--they are simply encoded, which means they are easily decoded--most "modern browsers" have a built-in function called Atob () that decodes the Base64 string.
The third part of the signature is encrypted, in order to decrypt it must use the server's key, and so-called key that is only on the server and can not be made public to the guy.

That sounds a little complicated! Don't worry, the good news is that you can easily fix a JWT with just one library installed.

Generating JWT on the server

The command to install the JWT build library is as follows:

$npminstalljsonwebtoken--save

Then introduce the Jsonwebtoken library into the code.

varrequire‘mongoose‘varrequire(‘crypto‘);varrequire(‘jsonwebtoken‘);

Finally we will add a GENERATEJWT method to the user model. To generate a JWT successfully we need to provide valid data (Payload) and keys. In the valid data we send the user's _id, email, name. We should also set a token expiration time--when the token expires, the user needs to log back in and get a new token, we use the reserved keyword "exp" of the JWT valid data (Payload) to deposit this expiration time. See Code for implementation:

function() {  varnewDate();      7//将过期时间设为7天????return jwt.sign({  this._id,  this.email,  this.name,  parseInt1000‘thisIsSecret‘//"thisIsSecret"是密钥};

Of course, the above code is a bit of a problem: The key is in plaintext in the code inside, we will solve it next.

Save the key as an environment variable

If you want to versioning your code-for example, with GitHub, you should never write your key in your code,-_-# to protect your key, it's a safe way to set it up with environment variables. Setting environment variables is simple, see an. env file below the root of the project, and then write the key inside:

JWT_SECRET=thisIsSecret

Then, make sure that the. env file is not uploaded to GitHub, and you have to write a. gitignore file:

# Dependency directorynode_modules# Environment variables.env

To read the. env file, you also want to install a library: dotenv

$npminstalldotenv--save

Then read the environment variables through DOTENV:

require(‘dotenv‘).load();varrequire(‘express‘);

Finally, let's look at the code after we introduce the environment variable:

function() {  varnewDate();  7);  return jwt.sign({    this._id,    this.email,    this.name,    parseInt1000),}, process.env.JWT_SECRET); };

Of course, there are many ways to set environment variables, this article will not repeat. Let's talk about how to use the Passport Library to manage user authentication.

3. Establish user authentication API through Passport

Passport is made by Jared Hanson
The design and development of the node. JS User authentication Library has the advantage of using a variety of authentication strategies, including:

    • Facebook
    • Twitter
    • Oauth
    • Local User name and password

This article only briefly describes the authentication policy for local user name passwords.

3.1 Installing and configuring the Passport

The installation commands are as follows:

--save$ npm install passport-local--save

After loading, we can configure the passport.

Create a Passport configuration file

We build a config directory in the project folder, in which we build a passport.js file, at the top of the file, we introduce the library to be used:

varrequire(‘passport‘);varrequire(‘passport-local‘).Strategy;varrequire(‘mongoose‘);var User = mongoose.model(‘User‘);
Configure Local Policies

The underlying framework for configuring code is as follows:

passport.use(new LocalStrategy({},  function(username, password, done) {  }));

By default, the local policy of the passport uses "username" and "password" as the field name, in this case we replace the username with an e-mail as the login name, so we need to make some changes. Fortunately, the passport allows us to reload username with the following code:

passport.use(new LocalStrategy(    ‘email‘  },  function(username, password, done) {  }));

The next main function, mainly rely on mongoose to find the corresponding user name, password, we have to complete the following several things:

    • User-provided email to find user profiles;
    • Verify that the password is correct;
    • If the validation is correct, return the user object;
    • If wrong, then error.

Since email is unique, we can use Mongoose's FindOne function to find the user, then we can use the Validpassword function written in the previous section to verify that the user provided the correct password, the code is as follows:

Passport. Use(NewLocalstrategy ({usernamefield:' Email '}, function(username, password, done) {User.findone ({email:username}, function (err, user) {      if(ERR) {returnDone (ERR); }??if(!user) {returnDoneNULL,false, {message:' wrong user name or password. '});}if(!user.validpassword (password)) {returnDoneNULL,false, {?? Message' wrong user name or password. '});}returnDoneNULL, user); });} ));

Of course, in the main file app.js also have to add a few lines:

varrequire(‘passport‘);require(‘./app_api/config/passport‘);app.use(passport.initialize());

This way, the passport is installed, configured and initialized successfully! Here's what we're going to do is the user login API endpoint.

3.2 Creating an API endpoint that returns a JSON Web tokens

Mean full stack development user authentication

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.