Front end security against CSRF attack

Keywords: Session OpenSSL MongoDB JQuery

The front end is not only to render the data on the page, but also to do a lot of things
For example, we should do a good job in safety

Suppose, a management system, when you log in the system, you do not do security work
Other people can add, delete, modify and check your data through your interface. This is the csrf attack
Data has changed and may have a significant impact on the company

To solve this problem, please refer to the following plan - this is my project
I annotated the steps related to the construction of the Express framework of Node for the backend

First, download a plug-in. I will introduce the use of this plug-in at the end of this chapter, or refer to the relevant jsonwebtoken documents

yarn add jsonwebtoken

Then, after the user logs in, set the token and user name for the return header
The front end is stored in local storage after receiving

_createJWT(username) {
	//This function generates a token
    let privateKey = fs.readFileSync(path.resolve(__dirname, "../key/rsa_private_key.pem"));
    return jwt.sign(username, privateKey, { algorithm: "RS256" });      //The last parameter is the encryption algorithm. For details, see https://www.npmjs.com/package/jsonwebtoken

  }

  async login(req, res) {
    let { username, password } = req.body;         //Get the content of req.body through the body parser plug-in
    let user = await UserModel.findOne({ username })       //mongoDB find user name

    if (!user) {
      res.send({ code: -1, message: "user does not exist" })
      return;
    }
    let rs = this._comparePwd(password, user["password"]);    //This is to encrypt the password. No, I'll explain it here
    if (rs) {
      //Store user name in session session
      req.session.username = user["username"];
      
      let token = this._createJWT(user["username"]);     //Generate token
      
      res.set("X-ACCESS-TOKEN", token);      // Set return header
      
      log.debug(user["username"] + ':Login successfully');
      
      res.send({ code: 1, username: user["username"], message: "User login successful" })
    } else {
      res.send({ code: -1, message: "User login failed" })
    }
  }

The front end can be stored in the local storage after receiving the request. When a request is initiated, a global interception is made
Judge whether the token is legal before operation
The front end of my project uses jQuery, so there is a global interceptor that can send requests first

$.ajaxSetup({
      beforeSend(xhr, setting) {
        let token = localStorage.getItem('token');
        xhr.setRequestHeader('x-access-token', token);
      },
      complete(xhr, setting) {
        if (xhr.responseJSON.code === 401) {
          alert(xhr.responseJSON.message)
          router.go('/index')
        }
      }
    })

When the backend performs operations, it can decide whether to execute or not through the next of middleware
First look at the configuration of the route

router.use(auth);     //If I want to add a position and execute the auth file first, this file is used to check whether the user has logged in and verify the token

router.post('/add', uploadfile, PosController.add)

auth.js

const jwt = require('jsonwebtoken');
const path = require('path');
const fs = require('fs');
const log = require('../util/log')

function auth(req, res, next) {
  try {
    let token = req.get('X-ACCESS-TOKEN');

    let publicKey = fs.readFileSync(path.resolve(__dirname, '../key/rsa_public_key.pem'));    //Public key decryption is used here (for use, please refer to the document or the last reference of this chapter)
    jwt.verify(token, publicKey, function (err, decode) {
      if (err) {
        res.send({ code: 401, message: "Illegal access" })
      } else {
        console.log('decode:', decode)
        if (decode === req.session.username) {
          next()
        } else {
          res.send({ code: 401, message: "Illegal access" })
        }
      }
    })

  } catch (error) {
    res.send({ code: 401, message: "Illegal access" })
    log.error(req.ip, error.message);
  }

}


module.exports = auth;

What are the benefits of doing so

1. The user cannot see the position information of the company without logging in
2. When the user logs in successfully and the csrf attacks, there is no token corresponding to me, and of course, it can not operate on my data and effectively prevent the csrf attacks

About the use of jsonwebtoken

1. You can use symmetric encryption

let result = jwt.verify(token,"crocess")   //You can change the value of cross at will

In the decrypted file

function auth(req,res,next){

    try {
        let token = req.get("X-ACCESS-TOKEN")
    let result = jwt.verify(token,"crocess")
    if(result !== req.session.username){
        res.send({code:401,message:"Illegal access"})
    }else{
        next()
    }
    } catch (error) {
        res.send({code:401,message:"Illegal access"})
    }
}

This is a simple encryption, easy to be cracked by third-party software

2. Using asymmetric encryption is not suitable to crack
1. Download address Window: http://slproweb.com/products/Win32OpenSSL.html
2. Open the cmd, and enter the command genrsa -out C:\OpenSSL-Win64\create_key/rsa_private_key.pem 1024 to generate the private key
3. Using private key to generate public key: rsa -in C:\OpenSSL-Win64\create_key/rsa_private_key.pem -pubout -out C:\OpenSSL-Win64\create_key/rsa_public_key.pem

Use as an example

  let privateKey = fs.readFileSync(path.resolve(__dirname, "../key/rsa_private_key.pem")); //Private key generation
 let publicKey = fs.readFileSync(path.resolve(__dirname, '../key/rsa_public_key.pem'))   //Public key decryption

The above is about the prevention of csrf attacks. Of course, the encryption algorithm can refer to the relevant documents

For front-end
I'm far from proficient
Just on the way

Published 9 original articles, won praise 7, visited 1554
Private letter follow

Posted by youdontmeanmuch on Mon, 24 Feb 2020 02:48:14 -0800