添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
淡定的斑马  ·  ExpertBook P5 (P5405) ...·  3 月前    · 
好帅的冲锋衣  ·  Latex ...·  1 年前    · 
冷冷的枕头  ·  人民周刊·  1 年前    · 
任性的小熊猫  ·  os.environ['mapreduce_ ...·  1 年前    · 

Implementing user authentication can be a difficult task, because we can use various libraries and authentication strategies . There are a lot of tutorials on this topic, but often times they miss fundamental information or don’t reflect set up of our project. In this blog post, I don’t attempt to write an universal tutorial for user authentication. However, I will point out some parts in authentication flow I didn’t find in other tutorials.

We will be building a user authentication in a single page application with Node, React, Redux and Koa combined with Passport. I think this is a standard set up for Node.js projects, but what we will build is principally applicable to any SPA with unidirectional data flow. We will implement local authentication, where users can log in using an email and passport. We will also add authentication with Facebook, which can be used with other social networks and OAuth providers .

You can find a lot of good tutorials, which will help you implement user authentication in Node.js projects, but all these projects are multiple page applications:

  • User Authentication with Passport and Koa
  • Local Authentication Using Passport in Node.js
  • Easy Node Authentication: Setup and Local
  • Build User Authentication with Node.js, Express, Passport, and MongoDB
  • Authenticating Users in a Node App using Express & Passport (Part One)
  • Authenticating Node.js Applications With Passport
  • If you are looking for how to implement user authentication in React.js or Redux, you will probably come across these tutorial, which are very helpful:

  • Secure Your React and Redux App with JWT Authentication
  • Tips to handle Authentication in Redux #2 introducing redux-saga
  • Protected routes and Authentication with React and Node.js
  • In preview below, you can see the result of this tutorial. You can check the source code on Github and deployed demo on Heroku .

    I will be using Koa framework, which is very similar to Express and popular authentication middleware library Passport . In this project, I use Redis for:

  • storing user’s session information
  • mocking a database with users
  • If you are looking for how to use PostgreSQL or MongoDB in Node.js, just check tutorials in the beginning of this article. For developing single page application, we will use React, React Router, Redux, Redux-Saga, Webpack and Twitter Bootstrap.

    Getting Started

    We will need to have Node , with npm , installed on our machine. We will also need to install Redis . Once all of the prerequisite software is set up, we can create the node application with the following command:

    $ npm init
    You’ll be prompted to put in basic information for Node project. We will need following dependencies.

    This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

    Show hidden characters We will also need other configuration files for React project such as webpack.config.js, .babelrc and others, which you can see in root folder of the project. Below is an overview of project structure. Back-end is located in server.js, serverConfig.js and auth.js files.

    ├── script
    │   ├── controllers
    │   │    └── auth.js
    │   ├── views
    │   │    ├── about
    │   │    │    └── AboutView.js
    │   │    ├── actions
    │   │    │    ├── access.actions.js
    │   │    │    └── modals.actions.js
    │   │    ├── components
    │   │    │    ├── App
    │   │    │    ├── Header
    │   │    │    └── LoginForm
    │   │    ├── home
    │   │    │    └── HomeView.js
    │   │    ├── sagas
    │   │    │    ├── access.sagas.js
    │   │    │    ├── index.js
    │   │    │    └── modals.sagas.js
    │   │    ├── state
    │   │    │    ├── access.reducers.js
    │   │    │    ├── index.js
    │   │    │    └── modals.reducers.js
    │   │    └── routes.jsx
    │   └── server.js
    │   └── serverConfig.js
    ├── index.html
    ├── index.jsx
    ├── package.json
    └── webpack.config.js
    

    Building and Setting up the Server

    Now, when we install all npm packages, we can start to implement the server for our Node.js project. We create server.js file in script folder.

    Application Setup server.js

    In the beginning of server.js file, we just add required modules and create koa application. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters If we want to refresh our server every time we change files, we need to use nodemon. Just install with: npm install -g nodemon and add new command into package.js file:
    "debug": "./node_modules/nodemon/bin/nodemon.js --inspect ./script/server.js"
    Now we can initialize Redis and create a mock database with a user.
          This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
          Learn more about bidirectional Unicode characters
      
    Show hidden characters In the first line, we initialized Redis, then we created a new key usersMockDatabase with a value – user object. We should always encrypt passwords before saving them to the database. In the code snippet above, I just pasted encrypted test string using online bcrypt-calculator. Next, we move session data out of memory into an external session store Redis. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters In the first line, you can see, we required ./controllers/auth.js file, where is handled all the passport implementation. This is where we configure our authentication strategy for local and facebook. We will add required libraries, modules and implement serializing and de-serializing the user information to the session. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters
  • X-Rate-Limit-Limit – the number of requests allowed in a given time interval
  • X-Rate-Limit-Remaining – how many calls user has remaining in the same interval
  • X-Rate-Limit-Reset – the time when the rate limit will be reset.
  • Most HTTP frameworks support it out of the box. For example, if you are using Koa and Redis, there is the
    koa-simple-ratelimit package. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters

    Building and Setting up the SPA in React and Redux

    Back-end part in Node.js is ready and now we can implement SPA in React and Redux. We will focus on unidirectional data flow in single page applications. The same principles can be applied to other frameworks or libraries for implementing unidirectional data flow such as Flux or MobX. In this project I decided to use popular libraries React, React-Router, Redux and Redux-Saga. Redux is a state container for JavaScript applicatins that describes the state of the application as a single object and Redux-Saga is used to make handling side effects in Redux nice and simple. Let’s start with implementing React entry point with views and other components.

    Main React Entry File

    At first we define index.jsx, which bootstraps the react + redux application by rendering the App component (wrapped in a redux
    Provider) into the div element defined in the base index.html. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters In LoginForm we implemented actions loginUser used for logging user with email and password. Another action toggleLogin is used for changing modal open state. Let’s say we want to display modal window for logging on other pages and in this case it is better to keep modal open state in a reducer instead of component’s state. We don’t use an action for logging users with Facebook, you can see the explanation below. We need to save our current URL location in cookies, which we will need after Facebook successful login redirect. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters You can not load the FB login dialog via XHR/AJAX in the background; you need to call/redirect to it in the top window instance. stackoverflow.com

    Redux Actions Folder

    Now we can implement actions. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters We don’t want to lose user data, when we refresh a page after login. If we take a look at login saga worker, we can see that response data, which contains user object is stored in cookies. We can store user data somewhere else, but we shouldn’t do it in the reducer, because reducers should have no side effects. We need to get user data in a reducer, when we initialize state.

    Ajax API Calls

    Now we can implement API calls. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters As you can see, we are using withCredentials property. If we use CORS and don’t set withCredentials to true, isAuthenticated returns false and this passport’s method doesn’t work.

    Redux Reducers Folder

    Next, we can implement reducers. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Show hidden characters After facebook successful redirect, we want to enter the page where we logged in. If we want to recognize in a React component, that we were redirected, we can use location state. After successful redirecting, we set a state loadUser, which will be used in componentWillReceiveProps method in Header component to get user profile data. If we want to make routes accessible only to authenticated users, we need to check documentation or tutorials on protected (authentication) routes for our routing library.

    React + Redux Header Component

    This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
    Theme by Colorlib Powered by WordPress