Node를 사용하여 로그인 시스템을 완료합니다.js&Vue.js | RestAPI & JWT | 섹션[1/2]

최초 발표webdeasy.de!
이 문서에서 Node를 사용하는 방법을 학습합니다.js, JWT(JSON WebTokens)와 MySQL은 사용자 인증을 위한 완전한 로그인 시스템을 만듭니다.
본고는 노드를 포함하는 완전한 로그인 시스템의 두 부분 시리즈의 첫 번째 부분이다.js&Vue.js.우리는 Node로 완전한 로그인 시스템을 실현하는 것을 책임진다.js는 백엔드 및 Vue로 사용됩니다.js를 전단으로 합니다.이 자습서는 두 부분으로 구성되므로 Vue에 바인딩할 필요가 없습니다.js 전단이지만 본고에서 개발한restAPI는 다른 전단에 적용될 수도 있고 각도나 반응에 적용될 수도 있습니다.
➡️ Part 2: Complete login system with Node.js & Vue.js | Vuex

섹션 1의 대상: JWT 및 MySQL을 사용한 API 재시작


노드를 만듭니다.로컬 서버에서 실행되는 js 프로그램입니다.우리는 MySQL 데이터베이스를 하나 가지고 있는데 그 중에는 우리의 사용자 데이터가 저장되어 있다.인증에 대해 우리는 이 데이터를 조회해야 하며 JWT 확장된 도움말 아래 사용자에게 세션을 열 수 있다.
마지막으로 실행 가능한 프로그램이 있습니다. this guide 의 도움으로 서버에 배치할 수 있습니다.하지만 이제 드디어 시작입니다!🙂

1. RestAPI란 무엇입니까?


RestAPI는 서버와 클라이언트 간의 인터페이스를 나타냅니다.정상적인 HTTP 요청을 통해 우리는 서버에 도착하여 프로그래밍 기능을 실행할 수 있다. 예를 들어 해당하는 비밀번호를 사용하여 사용자를 검증할 수 있다.
이 강좌는 절대 초보자에게 적합하지 않기 때문에, 나는 당신이 이미 노드에 대해 좀 익숙하다고 가정합니다.js, 이것이 바로 우리가 설치를 건너뛰고 감동적인 부분으로 들어가는 이유입니다.만약 그렇지 않다면, 당신은 here 가 아주 좋은 Node 입문 안내서라는 것을 발견할 수 있을 것입니다.js.

2. 종속성 설치


그래서 우리 노드는js 프로그램이 의존항을 설치할 준비가 되어 있습니다.다음 모듈이 필요합니다.

다음 CLI 명령을 사용하여 이러한 모듈을 설치합니다.
npm install bcryptjs body-parser express jsonwebtoken mysql uuid cors

3. 데이터베이스 구축


내가 사용하는 데이터베이스XAMPP에 대해 나는 로컬에서 자신의 데이터베이스를 위탁 관리할 수 있다.물론 다른 (원격) 데이터베이스도 사용할 수 있습니다.
로그인 시스템의 경우 다음 시나리오에 맞는 테이블이 필요합니다.

데이터베이스의 테이블은 다음과 같습니다.

이렇게 하면 우리도 우리의 노드를 통해 이 연결을 방문할 수 있다.js 프로그램에서, 우리는 자신의 클래스 파일을 만들고, 나중에 공유기에 포함합니다.
// lib/db.js
const mysql = require('mysql');
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'node-jwt',
  database: 'node-jwt',
  password: '********'
});
connection.connect();
module.exports = connection;

4. 고속 라우터 설정 및 라우팅 생성


우리의 입구 파일은 바로 색인이다.js와 웹 서버의 시작, 그리고 파일routes/router에 정의된 루트의 통합을 포함합니다.js.
// index.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
// set up port
const PORT = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use(cors());
// add routes
const router = require('./routes/router.js');
app.use('/api', router);
// run server
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
공유기에서.우리는 우리의 노선을 정의한 후에 논리를 그 안에 포장한다.우리가 이곳에서 추가 파일을 사용하는 이유는 그것의 명확성 때문이다.프로그램이 한 점에 20개 이상의 루트를 가지고 있으면 인덱스가 삭제됩니다.js가 혼란스러울 거야.이것이 바로 우리가 노선을 하청을 하는 이유다.
// routes/router.js
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const uuid = require('uuid');
const jwt = require('jsonwebtoken');
const db = require('../lib/db.js');
const userMiddleware = require('../middleware/users.js');
router.post('/sign-up', (req, res, next) => {});
router.post('/login', (req, res, next) => {});
router.get('/secret-route', (req, res, next) => {
  res.send('This is the secret content. Only logged in users can see that!');
});
module.exports = router;
여기에서, 우리는/api/등록 및/api/로그인을 할 수 있습니다.우리는 로그인한 후에만 호출할 수 있는 루트/비밀 루트가 있습니다.현재 모든 사용자가 접근할 수 있습니다.이따가 다시 이야기합시다.
열 번째 줄에는 데이터베이스에 연결된 파일도 포함되어 있습니다.
이 파일도 포함되어 있습니다/중간부품.js, 검증 요청을 포함하는 코드입니다.이것은 사용자가 비밀번호를 입력했는지, 사용자 이름이 가이드라인에 부합되는지 확인해야 한다는 것을 의미한다.다음에, 우리는 이 검색을 중간부품으로 루트 호출로 전환할 것이다.

5. 중간부품 만들기(검증)


중간부품은 두 구성 요소 사이를 전환하는 작은 프로그램이다.이런 상황에서, 우리의 요청과 실제 등록 사이에, 우리는 입력한 데이터를 검증할 중간부품이 하나 있다.등록의 경우 다음과 같이 유효성을 검사할 수 있습니다.
// middleware/users.js
module.exports = {
  validateRegister: (req, res, next) => {
    // username min length 3
    if (!req.body.username || req.body.username.length < 3) {
      return res.status(400).send({
        msg: 'Please enter a username with min. 3 chars'
      });
    }
    // password min 6 chars
    if (!req.body.password || req.body.password.length < 6) {
      return res.status(400).send({
        msg: 'Please enter a password with min. 6 chars'
      });
    }
    // password (repeat) does not match
    if (
      !req.body.password_repeat ||
      req.body.password != req.body.password_repeat
    ) {
      return res.status(400).send({
        msg: 'Both passwords must match'
      });
    }
    next();
  }
};
우리의/등록 경로를 호출할 때, 우리의 중간부품을 실행해야 합니다.이렇게 하려면 다음과 같이 태그 행을 변경합니다.
// routes/router.js
const express = require('express');
const router = express.Router();
const userMiddleware = require('../middleware/users.js');
router.post('sign-up', userMiddleware.validateRegister, (req, res, next) => {});
router.post('login', (req, res, next) => {});
module.exports = router;

6. 등록(또는 등록) 루트(과 JWT)


데이터베이스에 새 사용자를 추가하려면 사용자 이름이 아직 존재하지 않는지 확인해야 합니다.사용자가 있는 경우 오류 메시지가 표시됩니다.만약 사용자가 존재하지 않는다면, 우리의 모듈 bcrypt는 입력한 암호를 산열 (암호화) 하고 모든 데이터를 데이터베이스에 입력하는 데 사용할 것입니다.
// routes/router.js
router.post('/sign-up', userMiddleware.validateRegister, (req, res, next) => {
  db.query(
    `SELECT * FROM users WHERE LOWER(username) = LOWER(${db.escape(
      req.body.username
    )});`,
    (err, result) => {
      if (result.length) {
        return res.status(409).send({
          msg: 'This username is already in use!'
        });
      } else {
        // username is available
        bcrypt.hash(req.body.password, 10, (err, hash) => {
          if (err) {
            return res.status(500).send({
              msg: err
            });
          } else {
            // has hashed pw => add to database
            db.query(
              `INSERT INTO users (id, username, password, registered) VALUES ('${uuid.v4()}', ${db.escape(
                req.body.username
              )}, ${db.escape(hash)}, now())`,
              (err, result) => {
                if (err) {
                  throw err;
                  return res.status(400).send({
                    msg: err
                  });
                }
                return res.status(201).send({
                  msg: 'Registered!'
                });
              }
            );
          }
        });
      }
    }
  );
});
중요한 것은 기능db.escape()이다. 예를 들어 23줄.이렇게 하면 SQL 주입을 방지하기 위해 전달된 매개변수가 차단됩니다.사용자가 성공적으로 입력하면 상태 코드 201(작성됨)을 반환하고 함수 호출을 종료합니다.

7. 로그인(/Login) 경로(JWT 사용)


등록 과정을 제외하고 우리는 이미 등록한 사용자를 로그인시킬 수 있는 로그인 경로가 하나 더 있다.여기서 사용자 이름에 따라 해당하는 데이터베이스 항목을 검색할 수 있습니다.그리고 jwt.compare()의 도움말 아래 데이터베이스에서 입력한 비밀번호를 검사합니다.짧은 SQL 쿼리는 44번째 행의 마지막 로그인 날짜/시간을 현재 값으로 설정합니다.
// routes/router.js
router.post('/login', (req, res, next) => {
  db.query(
    `SELECT * FROM users WHERE username = ${db.escape(req.body.username)};`,
    (err, result) => {
      // user does not exists
      if (err) {
        throw err;
        return res.status(400).send({
          msg: err
        });
      }
      if (!result.length) {
        return res.status(401).send({
          msg: 'Username or password is incorrect!'
        });
      }
      // check password
      bcrypt.compare(
        req.body.password,
        result[0]['password'],
        (bErr, bResult) => {
          // wrong password
          if (bErr) {
            throw bErr;
            return res.status(401).send({
              msg: 'Username or password is incorrect!'
            });
          }
          if (bResult) {
            const token = jwt.sign({
                username: result[0].username,
                userId: result[0].id
              },
              'SECRETKEY', {
                expiresIn: '7d'
              }
            );
            db.query(
              `UPDATE users SET last_login = now() WHERE id = '${result[0].id}'`
            );
            return res.status(200).send({
              msg: 'Logged in!',
              token,
              user: result[0]
            });
          }
          return res.status(401).send({
            msg: 'Username or password is incorrect!'
          });
        }
      );
    }
  );
});
36행과 37행에서 JWT 토큰에 저장할 변수를 전달합니다.이렇게 하면 보호된 라우팅의 이러한 변수에 액세스할 수 있습니다.
39 줄에서 JWT 영패를 생성하는 키를 전달해야 합니다. 이것은 이후의 검증에 매우 중요합니다.여기에 문자열을 입력할 수 있습니다.
당신은 40줄에서 영패의 유효기간을 지정할 수 있습니다.여기서 1h 또는 3m 등의 값이 유효합니다.단일 값과 매개 변수에 대한 정보in the documentation도 읽을 수 있습니다.
암호 오류나 사용자 이름이 없으면 오류 메시지가 표시됩니다.이 메시지는 잠재적인 공격자가 단일 사용자 프로필이 존재하는 것에 대한 정보를 다른 방식으로 얻을 수 있기 때문에 고의로 동일합니다.
로그인에 성공하면 사용자 객체 및 JWT에서 생성한 토큰이 반환됩니다.이 영패는 로그인해야 하는 모든 경로에 매우 중요합니다.섹션 2(Vue.js Frontend)에서는 각 요청에 이 토큰을 전달하는 방법을 학습합니다.Postman를 사용하여 RestAPI를 테스트하는 경우 키 "Bearer key"를 다음 구문에 따라 값으로 지정할 수 있습니다.

8. 로그인을 통한 라우팅 보호


가장 중요한 노선은 지금 이미 준비가 다 되었다.새 사용자를 추가하고 기존 계정으로 로그인할 수 있습니다.지금 우리는 노선을 보호하고 싶다.이것은 등록된 사용자만 그것들을 방문할 수 있다는 것을 의미한다.
그래서, 우리는 사용자들 사이에서 새로운 중간부품을 만들었다.js.토큰은 요청한 헤드에서 가져와 JWT에서 검증합니다.
// middleware/users.js
isLoggedIn: (req, res, next) => {
  try {
    const token = req.headers.authorization.split(' ')[1];
    const decoded = jwt.verify(
      token,
      'SECRETKEY'
    );
    req.userData = decoded;
    next();
  } catch (err) {
    return res.status(401).send({
      msg: 'Your session is not valid!'
    });
  }
}
태그 행에 JWT 생성과 같은 키를 입력해야 합니다.
라우트를 즉시 보호하려면 다음과 같이 라우트를 호출할 때 이 중간부품을 포함해야 합니다.
// routes/router.js
router.get('/secret-route', userMiddleware.isLoggedIn, (req, res, next) => {
  console.log(req.userData);
  res.send('This is the secret content. Only logged in users can see that!');
});
req.userData에는 JWT 키에 저장된 데이터(본 예는 usernameuserId가 포함되어 있습니다.예를 들어, 이것은 데이터베이스에서 보호된 루트의 사용자 정의 값을 읽을 수 있도록 합니다.

9. 결론


➡️ 섹션 2: Complete login system with Node.js & Vue.js | Vuex | Part [2/2]
저것이렇게!첫 번째 섹션에서는 검증 및 세션 처리를 위해 애플리케이션에 대한 전체 RestAPI를 작성했습니다.이 시스템은 각도, 반응, Vue 등 프런트엔드에서 사용할 수 있습니다.
읽어주셔서 감사합니다!만약 당신이 이 문장을 좋아한다면, 내가 알고 공유할 수 있도록 해 주세요!만약 당신이 원한다면 체크아웃my blog할 수 있습니다. 따라오세요!😊

좋은 웹페이지 즐겨찾기