개발/library, framework

클라이언트에게 특정 상태에만 상태를 전송하는 방법...state.isAdmin (feat.Vue)

prpn97 2023. 8. 3. 22:11

발단

어드민페이지를 어드민 사용자에게만 노출하고, 그 외 일반사용자에게는 노출하지 않으려면 어떻게 해야 할까?

상태를 구분해서 어드민에게만 보여주면 된다.

지금까지는 vue를 사용하면서 VueX를 통해 전역적으로 상태를 관리했다.

예를 들면 로그인 여부, 어떤 페이지를 보여줄지, 에러메세지 등 여러가지를 온오프하는 방향으로 하여 한꺼번에 관리했는데,  사용자의 입장에서 굳이 관리자가 아니라는 상태를 알 필요가 없다고 느껴졌다. 

그래서 관리자일때만 관리자임을 알릴 수 있도록 하였다. 

 

해결과정

서버에서 관리자 여부를 클라이언트로 전송하는 방법은 여러가지가 있겠다.

내가 고민했던 부분을 나열해보려 한다. 

 

1. 토큰

이미 jwt에 role을 섞어서 보내고 있고, 클라이언트가 확인하고 해석하면 될까 싶지만 애초에 지금 고민하는 이 과정은 클라이언트가 확인할 수 없도록 하는 과정이고, 그렇기에 토큰 자체를 클라이언트에서 확인할 수 없도록 httponly를 설정했기 때문에 토큰으로는 확인할 수 없다. 

 

2. 포기하고 타협 ...ㅋㅋ

어차피 어떻게든 코드를 보면 isAdmin여부를 확인해서 페이지를 별도로 관리하고 있음을 알 수 있기도 하고, 백엔드 api에 접근하는 순간 미들웨어를 통해 어드민 여부를 검증하고 있기 때문에 클라이언트가 상태를 조작해서 페이지에 접근하더라도 안의 api에는 접근할 수 없다. 

그래서 일반적으로 관리자페이지를 노출하지는 않지만 상태 자체를 최대한 노출을 피하는 쪽으로 고민하다가 포기해야하나 싶었다. 

 

3. 서버에서 확인 후 관리자일 경우 / 아닐 경우 나누어 res 전송      (채택)

로그인할 때 입력하는 아이디로 관리자여부를 확인하고, 맞을 경우에는 res에 기본적으로 보내는 메세지에 role을 추가하여 보내고, 아닐 경우에는 토큰과 일반 메세지만 전송했다. 

여기까지는 사실상 고민하기 전부터도 방향중에 생각했던 부분인데, 클라이언트가 받을 때 상태관리할 때 신경쓴 부분이 꽤나 괜찮았던 것 같다. 

지금까지 관리하고 있는 스토어에서 관리하고 있는 상태는 다음과 같다. 

export const store = createStore({
  state: {
    isAuthenticated: false,
    loggedInUsername: null,
    provider: "Backtrack",
    showLoginModal: false,
    showRegisterModal: false,
    showRegisterSuccessModal: false,
    showFindUsernameModal: false,
    showFindPasswordModal: false,
    showGoogleLoginModal: false,
    showKakaoLoginModal: false,
  },
  mutations: {
    setAuthenticated(state, isAuthenticated) {
      state.isAuthenticated = isAuthenticated;
    },
   
    setIsAdmin(state, isAdmin) {
      if (isAdmin) {
        state.isAdmin = true;
      }
    },

여러가지가 있겠지만 그 중에서 어드민인지 파악하는 상태는 없다. 하지만 밑에 mutations를 보면, setIsAdmin에 매개변수 isAdmin을 넣는다. 그리고 isAdmin이 true일 경우에만 state.isAdmin 을 만들어준다. 기본적으로는 isAdmin이라는 상태가 없기 때문에 클라이언트는 알 수 없지만, 관리자로 로그인했을 때만 조건부로 isAdmin이라는 상태 자체가 생성된다. 

그리고 실제로 로그인할 때 관리자일 때만 role이 보이므로, role을 확인하고 setIsAdmin을 true로 만들어주었다. 

그리고 로그아웃할 때 관리자 여부와 상관없이 isAdmin이라는 state를 삭제해서 관리자가 흔적을 남기지 않도록 하였다. 

//로그인시
      if (response && response.data) {
          const { message, user, role } = response.data;

          if (role === "ADMIN") {
            this.$store.commit("setIsAdmin", true);
          }
        }



//로그아웃시
              this.setAuthenticated(false);
          this.$store.commit("setLoggedInUsername", null);
          this.$router.push("/");
          delete this.$store.state.isAdmin;   <<< isAdmin state 자체를 삭제

 

 

(좌) 관리자 / (우)일반 사용자

 

코멘트

아직 상태관리에 대해 디테일하게 알지는 못하지만, 그저 온오프에만 그치는 것이 아니라 특정 사용자에게만 보일 수 있도록 하는 상태도 관리하게 되어 기쁘다. 다른 미지의 영역이 어떤 것이 있는지 조차 상황을 아직 겪지 않아 모르지만 많이 겪어보면서 파악하고 싶다.

728x90