Токены в NodeJS

Node.js

JWT

1. Жетон

  • Что такое токен?

    Токен относится к учетным данным для доступа к ресурсам. Это метод аутентификации личности. Это самый популярный способ решения междоменной аутентификации.

  • Зачем использовать токен?

    В прошлом было более популярно использовать сеанс для аутентификации личности. Сеанс используется для аутентификации личности путем сохранения данных сеанса на сервере. Этот метод приведет к чрезмерной нагрузке на сервер при высокой степени параллелизма. Кроме того, если это кластер серверов , Тогда вам нужен общий доступ к сеансу сервера.

    Токен сохраняет данные сеанса не на сервере, а в клиенте. Токен хранится в заголовках каждого запроса, и сервер определяет действительность токена и возможность доступа к ресурсу.

  • Разница между традиционным токеном и JWT

    • Традиционный жетон

      Пользователь инициирует запрос на вход. После успешного входа токен возвращается и сохраняется в базе данных. Пользователю необходимо носить токен при доступе к ресурсам. Сервер получает токен и сравнивает его с базой данных.

    • JWT

      Пользователь инициирует запрос на вход, и токен возвращается после успешного входа в систему, но он не существует в базе данных.Пользователь должен носить токен при доступе к ресурсам.После того, как сервер получает токен, он проверяет действительность Жетон.

2. Процесс внедрения JWT

  • JWT разделен на три части: заголовок, полезная нагрузка, проверка подписи.

  • header

    Внутри содержит алгоритм подписи, тип токена, а затем преобразует его в строку с помощью алгоритма base64url.

    //明文例子:
    {
        "alg":"HS256",
        "typ":"JWT"
    }
    
  • payload

    Внутри содержит стандартные данные JWT и пользовательские данные, а затем преобразует их в строку с помощью алгоритма base64url.

    Общие стандартные данные JWT:

    • ИСС: провайдер.
    • sub: тема, обычно идентификатор пользователя.
    • exp: Срок годности.
    • иат: время создания.
    • jti: уникальный идентификатор токена.

    Необязательное использование вышеуказанных стандартных данных

    //明文例子:
    {
      "id": 3,
      "name": "Bmongo",
      "age": 18,
      "iat": 1588139323,
      "exp": 1588139333
    }
    

    Примечание. Поскольку JWT по умолчанию не зашифрован, не храните здесь конфиденциальную информацию.

  • verify signature

    Эта часть является подписью первых двух частей для предотвращения подделки данных.

    секрет - это ключ, сохраненный на стороне сервера, знает только сторона сервера, а затем используйте алгоритм подписи, указанный в заголовке, чтобы подписать две вышеуказанные части, и сгенерируйте подпись в соответствии со следующей формулой

    HMACSHA256(
        base64UrlEncode(header) + "." +
        base64UrlEncode(payload),
        secret
    )
    

    После вычисления подписи просто пропустите три части, разделите их и верните пользователю.

    Пример JWT:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAsIm5hbWUiOiLlvKDkuIkiLCJhZ2UiOjE2LCJpYXQiOjE1ODgxMzkzMjMsImV4cCI6MTU4ODEzOTMzM30.WzZp_aNgiw4iTsX7buxMhZe0z0e94Ve6ImEZ8L8L78c
    
  • запрос клиента

    Каждый запрос клиента должен принести этот токен, обычно записывая токен в заголовки запроса.

3. Используйте в Node.js

Использование JWT в Node.js

1. Начать

Генерация и проверка токена выполняются через пакет npm jsonwebtoken.

npm install --save jsonwebtoken
2. Сгенерируйте и проверьте токен
const jwt = require("jsonwebtoken")
//撒盐,加密时候混淆
const secret = '113Bmongojsdalkfnxcvmas'

//生成token
//info也就是payload是需要存入token的信息
function createToken(info) {
	let token = jwt.sign(info, secret, {
        //Token有效时间 单位s
		expiresIn:60 * 60 * 10
	})
	return token
}

//验证Token
function verifyToken(token) {
	return new Promise((resolve, reject) => {
		jwt.verify(token, secret, (error, result) => {
            if(error){
                reject(error)
            } else {
                resolve(result)
            }
		})
	})
}
3. Используйте
const express = require("express")
const app = express()
const jwt = require("jsonwebtoken")
//撒盐,加密时候混淆
const secret = '113Bmongojsdalkfnxcvmas'
const user = {
	id:10,
	name:"Bmongo",
	age:16,
}

//生成token
//info也就是payload是需要存入token的信息
function createToken(info) {
	let token = jwt.sign(info, secret, {
        //Token有效时间 单位s
		expiresIn:60 * 60 * 10
	})
	return token
}

//验证Token
function verifyToken(token) {
	return new Promise((resolve, reject) => {
		jwt.verify(token, secret, (error, result) => {
            if(error){
                reject(error)
            } else {
                resolve(result)
            }
		})
	})
}

//设置允许跨域
app.use(function(req, res, next) {
    //指定允许其他域名访问 *所有
	res.setHeader("Access-Control-Allow-Origin", "*");
    //允许客户端请求头中带有的
	res.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
    //允许请求的类型
	res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
	res.setHeader("X-Powered-By",' 3.2.1')
    //让options请求快速返回
	if(req.method=="OPTIONS") res.send(200);
	else  next();
});

//白名单
const whiteList = ['/login']

app.use((req,res,next) => {
	if(!whiteList.includes(req.url)) {
		verifyToken(req.headers.authorization).then(res => {
			next()
		}).catch(e => {
			res.status(401).send('invalid token')
		})
	} else {
		next()
	}
})

app.post('/login',(req,res) => {
	let token = createToken(user)
	res.json({token})
})

app.get("/api/info", (req,res) => {
	res.send({
		result:1,
		data:{
            "name":"Bmongo",
            "id":1
        }
	})
})

Оригинальная ссылка