ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Authentication 구축하기
    Project/트윗 클론코딩 2023. 9. 30. 19:27
    반응형

    크게 Auth에 관한 내용을 처리할 때 쿠키&세션을 활용하는 방법과 JWT를 사용하는 방법이 있다.

    이 둘엔 장단점과 차이점이 있는데 이에 관한 포스팅은 전에 올린 적이 있으니

    아래 글에서 확인하면 좋을 것같다.

     

    우리 트윗 클론코딩은 브라우저만 상대하는 게 아닌 여러 클라이언트를 상대하는

    RESTful API를 사용하고 세션의 정보를 얻기 위해 하나의 db에 접속할 필요가 없고

    확장성을 확보하기 위해 JWT를 사용하도록 결정했다.

     

    요청 메소드 req res 비고
    /auth/signin POST {id : text, pw : text} {jwt : jwt, username : text} / 200  
    /auth/signup POST {id :text,
    pw : text,
    username : text,
    name : text,
    email : email,
    url : url}
    201  

    이런식으로 API를 사용하면 되지 싶은데 강의에선 어떻게 했는지 아래에 또 적어보겠다

    ---------------------------------------------------------------------------------------------------------------

     

    Auth

    User Schema

     id: string // 사용자의 고유한 아이디

    username: string, // 사용자 닉네임 (아이디)

    password: string, // 사용자 비밀번호

    name: string, // 사용자 이름

    email: string, // 사용자 이메일

    url: string (optional) // 사용자 프로파일 사진 URL }

     

    주소 메소드 req res 비고
    /auth/signup POST {username,
    password,
    name,
    email,
    url
    }
    {token,
    username}
     
    /auth/login POST {username,
    password}
    {token,
    username}
     
    /auth/me GET   {token,
    username}
     

     

    나는 내가 흔히 쓰는 id를 스키마에서 똑같이 썼는데

    db에서 고유하게 식별가능한 id와 사용자가 로그인 할 때 쓰는 id(username)을 다르게

    가져가야 한다는 점을 내가 간과했던 것 같다.

    그리고 /me는 백엔드에서 사용자가 token을 가지고 있는지 확인 할때 쓰는 용도라고 배웠다

    이제 이를 적용해서 로그인도 구현해보자

     

     

    앞서 모델 뷰 컨트롤러 패턴으로 구현했기 때문에 로그인도 비슷하게 구현해보겠다.

    import express from "express";
    import { body } from "express-validator";
    import { loginTweet, signUpTweet } from "../data/auth.js";
    
    const router = express.Router();
    
    router.post(
      "/login",
      [
        body("username").trim().notEmpty("이름을 확인해주세요"),
        body("password")
          .isLength({ min: 2, max: 500 })
          .withMessage("최소 2글자 이상 입력해야 합니다"),
      ],
      loginTweet
    );
    router.post(
      "/signup",
      [
        body("username").trim().notEmpty("ID를 입력해주세요"),
        body("password")
          .isLength({ min: 2, max: 500 })
          .withMessage("최소 2글자 이상 입력해야 합니다"),
        body("name").trim().notEmpty("이름을 입력해주세요"),
        body("email")
          .trim()
          .notEmpty("이메일을 입력해주세요")
          .isEmail()
          .withMessage("형식에 맞게 입력해주세요"),
      ],
      signUpTweet
    );
    router.get("/me");

    내가 구현한 authRouter인데 /me에 관한 부분은 어떻게 처리해야 할 지 몰라서 남겨놨다.

    그리고 컨트롤러로 넘어가기 전에 validation으로 불필요한 요청을 컷트해내는 코드를 적어놨다.

     

    import { loginTweet, signUpTweet } from "../data/auth.js";
    
    export function login(req, res, next) {
      const id = req.body.id;
      const password = req.body.password;
    
      const user = loginTweet(id, password);
      if (user) {
        res.status(200).json(user);
      } else {
        res.status(404).json();
      }
    }
    
    export function signUp(req, res, next) {
      const user = signUpTweet(req.body);
      if (user) {
        res.status(200).json(user);
      } else {
        res.status(404).json({ message: "ID 혹은 Password가 일치하지 않습니다" });
      }
    }
    
    export function me(req, res) {
      const user = verifyUser();
      if (user) {
        res.status(200).json(user);
      } else {
        res.status(404).json();
      }
    }

    여긴 컨트롤러 부분인데 라우터에서 검증을 거쳤으므로 얻은 데이터를 직접적으로 기능을 수행하는 함수에 연결한다

    여기서 검증을 한 번 더 거치는 단계를 추가하면 더욱 견고한 코드가 되겠다..라는 생각을 해본다..

     

    let users = [
      {
        id: 1,
        username: "doyun",
        password: "1234",
        name: "Doyun",
        email: "dy__z@nate.com",
        url: "",
      },
    ];
    
    export function loginTweet(id, password) {
      const user = users.find((e) => e.username == id && e.password == password);
      if (user) {
        return { token, username };
      }
    }
    
    export function signUpTweet(data) {
      const { username, password, name, email, url } = data;
      const user = {
        id: new Date().toString(),
        username,
        password,
        name,
        email,
        url,
      };
      users.push(user);
      return { token, username };
    }

    여기가 data영역이다

    전달받은 id와 pw가 일치하면 토큰과 유저네임을 리턴한다.

    회원가입도 id를 생성하고 토큰을 리턴해준다.

    /me에 관한 유저를 식별하는 기능은 아직 없으니 강의를 보고 추가해줘야겠다.

    반응형

    'Project > 트윗 클론코딩' 카테고리의 다른 글

    XSS와 CSRF에 대응하기  (1) 2023.10.23
    Authentication 최종 정리  (0) 2023.10.02
    서버에서 Validation & Sanitization 수행하기  (0) 2023.09.24
    서버 아키텍쳐 구축하기  (0) 2023.09.23
    REST API 서버 구축하기  (0) 2023.09.22

    댓글

Designed by Tistory.