노드에 JSON 웹 토큰을 사용합니다.js

29354 단어 nodejavascript
아마도 웹 사이트, 모바일, 데스크톱 프로그램에 사용할 API를 계속 개발하고 있을 것이다.Api에서 인증과 권한 부여를 어떻게 실현하는지 신속하고 간단하게 배워야 합니다.
분명히 cookies,sessions와JWT 등 몇 가지 가장 유행하는 전략이 있다.그러나 최근 몇 년 동안 OAuth와 같은 제3자 서비스의 사용이 매우 유행하고 있다.그러나 사용자의 민감한 데이터를 다른 회사에 제공할지 여부에 대해 나는 줄곧 침묵을 지켰다.
OAuth를 실현하는 것은 최소한 서버에서는 도전적일 수 있다는 점도 덧붙이고 싶다.그러나 본문에서 나는 JWT에 대해 토론하고 간단한 실현 예시를 제시할 것이다.

JWT란?


JSON 웹 토큰이나 JWT는 상호 간에 정보를 안전하게 전송하는 데 사용되는 방법입니다.그것들은 기본적으로 일종의 신분 검증과 권한 수여 메커니즘의 실현으로 이런 메커니즘은 이미 상당히 보편적이다.
JWT의 예:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Nywicm9sZSI6ImNhcHRhaW4iLCJpYXQiOjE2MjE5NTc4MzF9.Rt2gvcnAVXXKYIbVsmee3qKeGkAWuytLzjZEc6jwUu8
JWT는 세 부분으로 나뉜다.JWT의 첫 번째 부분에서 영패의 유형과 사용하는 해시 알고리즘을 설명하는데 보통 헤더라고 부른다.
{
  "alg": "HS256",
  "typ": "JWT"
}
두 번째 부분은 영패의 기본 부분이다. 이것은 우리가 추가한 우리와 관련된 정보를 찾을 수 있기 때문에 통상적으로 유효 하중이라고 부른다.
{
  "id": 7,
  "role": "captain",
  "iat": 1621964911,
  "exp": 1621968511
}
JWT의 세 번째 부분이자 마지막 부분은 헤더, 유효 하중, 키를 기반으로 한 서명입니다.
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  YOUR_256_BIT_SECRET_KEY
) secret base64 encoded
이제 우리는 간단한 생각이 하나 생겼다. 우리가 인코딩을 하자.

저희가 인코딩을 해볼게요.


이전과 같이 우리는 먼저 다음과 같은 시설을 설치할 것이다.
npm i express jsonwebtoken
현재 의존 항목을 설치했습니다. 간단한api를 만듭니다.
const express = require("express");

const app = express();

app.get("/", (req, res) => {
  return res.json({ message: "Hello World 🇵🇹 👋" });
});

const start = (port) => {
  try {
    app.listen(port, () => {
      console.log(`Api up and running at: http://localhost:${port}`);
    });
  } catch (error) {
    console.error(error);
    process.exit();
  }
};
start(3333);
우선, jwt라는 의존항jsonwebtoken을 가져옵니다.그리고 http 동사 GET를 사용하여 단점 '/login' 을 만들 것입니다. (이 예에서는 본문에서 데이터를 보내지 않지만 보내려면 POST를 사용해야 합니다.)이렇게:
app.get("/login", (req, res) => {
  // Logic goes here
});
이제 jwt에 서명합시다.첫 번째 파라미터에서 유효 부하에 저장하고 싶은 데이터를 전달합니다. 두 번째 파라미터에서 키를 분배하고, 세 번째 파라미터는 영패의 만료 시간입니다. (이 예에서 1시간만 지속됩니다.)마지막으로, 우리는 응답 중에 영패를 되돌릴 것이다.
app.get("/login", (req, res) => {
  const token = jwt.sign({ id: 7, role: "captain" }, "YOUR_256_BIT_SECRET_KEY", { expiresIn: '1h' });
  return res.json({ token });
});
현재, 만약 우리가 첫 번째 클라이언트에서api를 테스트하려고 한다면, 우리는 비슷한 응답을 해야 한다.

이제 JWT를 만들 수 있으므로 인증을 완료했습니다.허가서가 없어졌어요.따라서 요청에 JWT가 있는지 확인하기 위해 authorization이라는 중간부품을 만들 것입니다.그렇지 않으면 컨트롤러에 대한 접근이 거부되어 보호됩니다.
그래서 우리는 우리의 중간부품을 만들어야 한다.
const authorization = (req, res, next) => {
  // Logic goes here
};
우선, 우리는 권한 수여 헤더가 있는지 확인해야 한다. 만약 없다면, 우리는 즉시 컨트롤러에 접근하는 것을 금지할 것이다.
const authorization = (req, res, next) => {
  const { authorization } = req.headers;
  if (!authorization) {
    return res.sendStatus(403);
  }
  // More logic goes here
};
라이센스 헤드가 있으면 다음과 같습니다.
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Nywicm9sZSI6ImNhcHRhaW4iLCJpYXQiOjE2MjE5NjAwMTZ9.oWhqt6Nlnfol9uv5rk29_7TTtptQXtT9Kpd97MW4f_g
그러나 우리는 승재자가 아니라 영패만 필요합니다. 따라서 영패를 구분하는 공백에서 문자열을 나누고, 영패만 필요합니다. 아래와 같습니다.
const authorization = (req, res, next) => {
  const { authorization } = req.headers;
  if (!authorization) {
    return res.sendStatus(403);
  }
  const token = authorization.split(" ")[1];
  // Even more logic goes here
};
이제 우리는 영패가 있으니, 우리는 그것을 검증하기만 하면 된다.이를 위해, 우리는 첫 번째 파라미터에서, 우리가 이전에 얻은 영패를 전달하고, 두 번째 파라미터에서 키를 전달해야 한다.
이런 방식을 통해 우리는 영패의 유효 부하에 접근할 수 있지만, 오류가 발생하면 컨트롤러에 접근하는 것을 금지할 것이다. 이것은 영패가 우리가 생성한 것이 아닐 수도 있고, 누군가가 가짜 영패를 사용하여 우리의 Api를 사용하려고 시도할 수도 있기 때문이다.
const authorization = (req, res, next) => {
  const { authorization } = req.headers;
  if (!authorization) {
    return res.sendStatus(403);
  }
  const token = authorization.split(" ")[1];
  try {
    const data = jwt.verify(token, "YOUR_256_BIT_SECRET_KEY");
    // Almost done
  } catch {
    return res.sendStatus(403);
  }
};
영패의 유효 부하 값에 쉽게 접근할 수 있도록 요청 대상에서 새로운 속성을 설명할 때입니다.
이를 위해, 우리는req를 만들 것입니다.유효 하중의 userId는 assign입니다.
const authorization = (req, res, next) => {
  const { authorization } = req.headers;
  if (!authorization) {
    return res.sendStatus(403);
  }
  const token = authorization.split(" ")[1];
  try {
    const data = jwt.verify(token, "YOUR_256_BIT_SECRET_KEY");
    req.userId = data.id;
    // Just a bit more
  } catch {
    return res.sendStatus(403);
  }
};
우리는 또한 req를 만들 것이다.사용자Role 및 토큰 로드에 존재하는 역할의 값을 할당합니다.컨트롤러에 권한을 주고
const authorization = (req, res, next) => {
  const { authorization } = req.headers;
  if (!authorization) {
    return res.sendStatus(403);
  }
  const token = authorization.split(" ")[1];
  try {
    const data = jwt.verify(token, "YOUR_256_BIT_SECRET_KEY");
    req.userId = data.id;
    req.userRole = data.role;
    return next();
  } catch {
    return res.sendStatus(403);
  }
};
중간부품이 완성되면 Api에 새 루트를 만들고 추가하기만 하면 요청에 표시된 새 속성을 사용할 수 있습니다.이렇게:
app.get("/protected", authorization, (req, res) => {
  return res.json({ user: { id: req.userId, role: req.userRole } });
});
최종 코드는 다음과 같습니다.
const express = require("express");
const jwt = require("jsonwebtoken");

const app = express();

const authorization = (req, res, next) => {
  const { authorization } = req.headers;
  if (!authorization) {
    return res.sendStatus(403);
  }
  const token = authorization.split(" ")[1];
  try {
    const data = jwt.verify(token, "YOUR_256_BIT_SECRET_KEY");
    req.userId = data.id;
    req.userRole = data.role;
    return next();
  } catch {
    return res.sendStatus(403);
  }
};

app.get("/", (req, res) => {
  return res.json({ message: "Hello World 🇵🇹 👋" });
});

app.get("/login", (req, res) => {
  const token = jwt.sign({ id: 7, role: "captain" }, "YOUR_256_BIT_SECRET_KEY", { expiresIn: '1h' });
  return res.json({ token });
});

app.get("/protected", authorization, (req, res) => {
  return res.json({ user: { id: req.userId, role: req.userRole } });
});

const start = (port) => {
  try {
    app.listen(port, () => {
      console.log(`Api up and running at: http://localhost:${port}`);
    });
  } catch (error) {
    console.error(error);
    process.exit();
  }
};
start(3333);
이제 Api를 가장 좋아하는 클라이언트에서 다시 테스트하지만 이번에는 토큰을 보내지 않고 보호 경로를 테스트하면 다음과 같은 응답을 받을 수 있습니다.

그러나 토큰을 보내면 다음과 같은 응답이 제공됩니다.

그럼 너는?


어떤 인증 정책/방법을 사용하고 계십니까?

좋은 웹페이지 즐겨찾기