Iron-session, API(confirm, me)

김종민·2022년 8월 2일
0

apple-market

목록 보기
14/37


들어가기
iron-session은 서명, 암호화된 쿠키를 사용하는 NodeJS 세션도구
https://github.com/vvo/iron-session
npm i iron-session
JWT와 비슷한 기능이라고 생각하면됨.
이 기능을 통해서 cookie에 session을 저장해서 authrization이 가능해짐.
req.session.user
JWT토큰이 localstorage에 저장되는 것과 비슷함.

1. libs/server/withSession.ts

npm i iron-session

import { withIronSessionApiRoute } from 'iron-session/next'
///import를 잘 봐 놓을것!!

declare module 'iron-session' {
  interface IronSessionData {
    user?: {
      id: number
    }
  }
} ///token을 받으면, memory의 cookie에 req.session.user로
  ///save를 할 것이라, session.user의 type을 설정해 준다.

const cookieOptions = {
  cookieName: 'applesession',
  password: process.env.COOKIE_PASSWORD!, ///!반드시 필요, .env에 암호설정
}
///cookie에 session을 저장하기 위해서는 cookieOptions가 설정되어야 함.

export function withApiSession(fn: any) {
  return withIronSessionApiRoute(fn, cookieOptions)
}
///함수와 cookieOptions를 받아서 withIronSessionApiRoute를 return해주는
///withApiSession 함수를 export해줌.

///이제, session관련 작업을 하기 위해서는 withApiSession으로 
///감싸주아야 함. (ex.login된 유저만 홈으로 갈 수 있게! 등등)
///아래의 confirm.tsx와 me.tsx에 적용되는 과정을 확인해보자

2. pages/api/users/confirm.tsx

client에서 /api/users/confirm으로 요청이 오면 처리하는 API

import withHandler, { ResponseType } from '@libs/server/withHandler'
import { NextApiRequest, NextApiResponse } from 'next'
import client from '../../../libs/server/client'
import { withApiSession } from '@libs/server/withSession'

async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseType>
) {
  ///윗 부분은 모든 API에 공통적으로, 동일하게 적용됨
  
  const { token } = req.body ///front에서 '/api/users/confirm으로 보낸
                             ///data(token)을 req.body로 받음.
                             
  const foundToken = await client.token.findUnique({
    where: {
      payload: token,
    },
    include: { user: true },
  })
  ///front에서 보내온 token을 가지고 DB에서 token을 찾음.
  ///prisma의 model token은 user랑 relation되어 있어서,
  ///include:{user:true}하면, 찾은 token과 연결되어 있는 user의 data를
  ///같이 불러올 수 있음.
  
  if (!foundToken) return res.status(404).end()
   ///DB에서 fornt에서 보낸 token을 못찾으면, 404에러 날림
  
  req.session.user = {
    id: foundToken?.userId,
  }
 ///매우중요!!
 ///req.session.user에 front에서 보낸 token으로 DB에서 찾은
 ///token에 relation된 userId를 id에 넣어줌.
  
  await req.session.save()
  ///userId를 넣은 req.session을 저장함
  ///그러고 나면, front에서 F12누르고 appplication부분의 cookie에 session이
  ///생긴것을 확인 가능함.
  
  await client.token.deleteMany({
    where: {
      userId: foundToken.userId,
    },
  })
  ///session에 user가 save됬으면, token을 delete함.
  ///이유는 login시 token을 받는데, 여런번 login하면, DB에 token이
  ///하나의 유저에 계속해서 생기기때문임.
  
  res.json({ ok: true })
  ///여기까지 error없이 왔다면, ok:true를 날려줌!
}

export default withApiSession(
  withHandler({ method: 'POST', handler, isPrivate: false })
)
///!!!매우중요. session에 user.id를 넣고, session을 저장하고 등등의
///session작업을 하기 위해서는 반드시 withApuSession으로 감싸주어야 함.

3. pages/api/users/me.tsx

/api/users/me로 요청이 왔을때, 처리하는 page.
cookie에 저장되있는 session을 통해서 login된 user가 누구인지 확인 가능하다.
req.session.user에 userId를 담아놓았기 때문에

import withHandler, { ResponseType } from '@libs/server/withHandler'
import { NextApiRequest, NextApiResponse } from 'next'
import client from '../../../libs/server/client'
import { withApiSession } from '@libs/server/withSession'

async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseType>
) {
///모든 API에서 윗부분은 공통적으로 적용

  const profile = await client.user.findUnique({
    where: { id: req.session.user?.id },
  })
  res.json({
    ok: true,
    profile,
  })
}
///session에 담겨져 있는 user.id를 가지고, DB에서 user를 찾는다.
///찾은 다음 ok:true, profile을 return해준다.
///const profile로 찾았기떄문에 profile을 return해 주는것임.

export default withApiSession(
  withHandler({
    method: 'GET',
    handler,
  })
)
///session을 다루기 때문에 withApiSession으로 감싸주었고,
///Data만 받기 떄문에, GET이고, handler는 위의 함수이름.
///그리고 isPrivate는 default 값으로 true라고 해주어서 생략됨.

notice!!!
authrization과정은 user의 정보를 받아서 cookie의 session에 저장시킨 다음,
session에서 loggedInUser의 정보를 받고, login을 유지시켜주는 과정을 함.
그리고 req.session.user로 req시 user의 info가 같이 붙음.

profile
코딩하는초딩쌤

0개의 댓글