[Узел] Использование koa2 для реализации простой аутентификации JWT

Node.js внешний интерфейс
[Узел] Использование koa2 для реализации простой аутентификации JWT

Введение в JWT

Что такое JWT

полное имяJSON Web Token, в настоящее время является самым популярным решением для междоменной аутентификации. Базовая реализация заключается в том, что после аутентификации сервераJSONобъект, отправленный обратно пользователю. Когда пользователь связывается с сервером, он должен отправить обратно этоJSONобъект.

ДолженJSONАналогично следующему:

{
  "姓名": "张三",
  "角色": "管理员",
  "到期时间": "2018年7月1日0点0分"
}

Зачем нужен JWT

Давайте сначала рассмотрим общий процесс сертификации, основанный наsession_idа такжеCookieвыполнить

  • Пользователь отправляет имя пользователя и пароль на сервер.
  • После аутентификации сервера в текущем сеансе (session) для хранения соответствующих данных, таких как роли пользователей, время входа в систему и т. д.
  • Сервер возвращаетsession_id, написанное пользователюCookie.
  • Каждый последующий запрос от пользователя будет проходить черезCookie,Будуsession_idотправлен обратно на сервер.
  • сервер получаетsession_id, найти данные, сохраненные в предыдущий период, и, таким образом, узнать личность пользователя.

Но тут есть большая проблема,Если это кластер серверов, требуется совместное использование данных сеанса, и каждый сервер может читать сеанс. Стоимость реализации относительно велика.

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

Структура данных JWT

JWTТри части следующие:

  • Header(заголовок), похожий на следующий
{
  "alg": "HS256",
  "typ": "JWT"
}

algАтрибут представляет собой алгоритм подписи (algorithm), значение по умолчаниюHMAC SHA256(пишется какHS256).typатрибут представляет этот токен (token)тип(type),JWTТокен записывается единообразно какJWT

  • Payload(нагрузка). такжеJSONиспользуется для хранения данных, которые на самом деле должны быть переданы.JWTОпределены семь официальных полей. Следующим образом

  • iss (эмитент): Эмитент

  • exp (время истечения): время истечения

  • суб (тема): тема

  • aud (аудитория): аудитория

  • nbf (не раньше): время действия

  • iat (выпущено в): выдано в

  • jti (идентификатор JWT): номер

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

  • Signature(подписать).SignatureЭта часть представляет собой подпись к первым двум частям для предотвращения подделки данных. Во-первых, вам нужно указать ключ (secret). Этот ключ известен только серверу и не может быть раскрыт пользователю. Затем используйтеHeaderУказанный внутри алгоритм подписи (по умолчаниюHMAC SHA256) для создания подписи по приведенной ниже формуле.
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

После вычисления подписи поставьтеHeader,Payload,SignatureТри части объединяются в строку, каждая часть отделяется точкой (.), и ее можно вернуть пользователю. Следующим образом

Безопасность JWT

  • JWTПо умолчанию не зашифровано, но его также можно зашифровать.JWTСекретные данные не могут быть записаны без шифрованияJWT

  • JWTОн содержит информацию об аутентификации, и после ее утечки любой может получить все разрешения токена. Чтобы уменьшить незаконное присвоение,JWTСрок действия должен быть установлен относительно коротким. Для некоторых более важных разрешений пользователь должен пройти повторную аутентификацию при использовании

  • Чтобы уменьшить незаконное присвоение,JWTне следует использоватьHTTPПротокол передачи чистого кода, для использованияHTTPSпередача протокола

Простая демонстрация Node — реализация Koa JWT

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

Во-первых, после того, как пользователь входит в систему, сервер генерирует и возвращает информацию о пользователе.tokenДайте его клиенту, фронтенд поставит его в следующем запросеtokenПринесите его на сервер, после того как сервер проверит, что он действителен, он вернет данные. Если недействительно, вернуть401код состояния

Здесь мы используемNodeРеализация, две основные используемые библиотеки:

  • jsonwebtoken, может генерироватьtoken, контрольная сумма и т.д.
  • промежуточное ПО koa-jwtправильноjsonwebtokenДальнейшая инкапсуляция, в основном используемая для проверкиtoken

Быстро построить проект koa

Выяснено, что у официалов на данный момент нет быстрой сборкиkoaпуть проекта, какVue-cliТакой же. (возможно построитьkoaСтоимость проекта также невысока). Но ленивый я все же нашел инструмент——koa-generator, он относительно прост в использовании, как показано ниже.

  • Установить
npm install -g koa-generator
  • koa2 my-projectСоздайте новый с именемmy-projectизkoa2проект
  • cd my-projectа такжеnpm install
  • Стартовый проектnpm start
  • Открытьlocalhost:3000

Создать токен

Для удобства демонстрации я прямо определяю переменные здесьuserListХраните информацию о пользователе, правда должна храниться в базе данных.

const crypto = require("crypto"),
  jwt = require("jsonwebtoken");
// TODO:使用数据库
// 这里应该是用数据库存储,这里只是演示用
let userList = [];

class UserController {
  // 用户登录
  static async login(ctx) {
    const data = ctx.request.body;
    if (!data.name || !data.password) {
      return ctx.body = {
        code: "000002", 
        message: "参数不合法"
      }
    }
    const result = userList.find(item => item.name === data.name && item.password === crypto.createHash('md5').update(data.password).digest('hex'))
    if (result) {
      const token = jwt.sign(
        {
          name: result.name
        },
        "Gopal_token", // secret
        { expiresIn: 60 * 60 } // 60 * 60 s
      );
      return ctx.body = {
        code: "0",
        message: "登录成功",
        data: {
          token
        }
      };
    } else {
      return ctx.body = {
        code: "000002",
        message: "用户名或密码错误"
      };
    }
  }
}

module.exports = UserController;

пройти черезjsonwebtokenизsignметод созданияtoken. Первый параметр этого метода относится кPayload(загрузка), используется для кодирования и сохранения вtokenДанные также являются проверкойtokenданные доступны позже. Второй — секретный ключ, уникальный для сервера.Обратите внимание, что то же самое можно расшифровать только при проверке, и это конфиденциально., вообще, лучше всего задать публичную переменную, вот только для удобства демонстрации, прямо на смерть запиши. Третий параметрoption, который можно определитьtokenСрок действия

Клиент получает токен

Войдите в систему, чтобы получитьtokenзатем можно сохранить вcookieтакже можно хранить вlocalStorageсередина. Я сохранил это прямо здесьlocalStorageсередина

login() {
  this.$axios
    .post("/api/login", {
      ...this.ruleForm,
    })
    .then(res => {
      if (res.code === "0") {
        this.$message.success('登录成功');
        localStorage.setItem("token", res.data.token);
        this.$router.push("/");
      } else {
        this.$message(res.message);
      }
    });
}

упаковкаaxiosПерехватчик, каждый раз, когда делается запросtokenОтправьте заголовок запроса на сервер для проверки. Вот если поставить передCookie, вы можете разрешить автоматическую отправку, но это не может быть междоменным. Поэтому рекомендуется помещать его в заголовок HTTP-запроса.Authorization, заметьте здесьAuthorizationнастройки, которым предшествуетBearer . Подробности можно узнатьBearer Authentication

// axios 请求拦截器处理请求数据
axios.interceptors.request.use(config => {
  const token = localStorage.getItem('token');
  config.headers.common['Authorization'] = 'Bearer ' + token; // 留意这里的 Authorization
  return config;
})

проверить токен

использоватьkoa-jwtПромежуточное ПО проверено, метод относительно прост, как показано ниже.

// 错误处理
app.use((ctx, next) => {
  return next().catch((err) => {
      if(err.status === 401){
          ctx.status = 401;
        ctx.body = 'Protected resource, use Authorization header to get access\n';
      }else{
          throw err;
      }
  })
})

// 注意:放在路由前面
app.use(koajwt({
  secret: 'Gopal_token'
}).unless({ // 配置白名单
  path: [/\/api\/register/, /\/api\/login/]
}))

// routes
app.use(index.routes(), index.allowedMethods())
app.use(users.routes(), users.allowedMethods())

Следует отметить следующие моменты:

  • secretдолжен иsignбыть последовательным
  • в состоянии пройтиunlessНастройте белый список интерфейса, которыйURLЭто можно проверить без проверки, например, вход/регистрация без проверки
  • Промежуточное программное обеспечение проверки должно быть размещено перед маршрутом, который необходимо проверить, и не можетURLчек об оплате

демо

  • Если вы напрямую обращаетесь к интерфейсу, требующему входа в систему, он401

  • Сначала зарегистрируйтесь, затем войдите в систему, иначе вам будет предложено ввести неверное имя пользователя или пароль.

  • Принесите его после входа в системуAuthorization, можно получить доступ в обычном режиме, вернуться200и правильные данные

Суммировать

В этой статье обобщаютсяJWTзнания, связанные с аутентификацией, и предоставляетkoa2Простота реализацииdemo, я надеюсь быть полезным.

Тема космическая, имею возможность поговорить о ней отдельноkoa-jwtИсходный код относительно прост~

эта статьяdemoадрес:Clientа такжеServer

Ссылаться на