Vue 3에서 토큰 인증 처리

내가 본 많은 Vue 프레젠테이션은 인증 용례를 고려하지 않았다.나의 몇몇 과정 시범에서 나는 어쩔 수 없이 그것을 깊이 연구했다.
나는 이것이 내가 배운 지식을 공유하는 좋은 장소일 수도 있고, 내 관중들이 내가 하고 있는 일에 대해 코드 심사를 할 수도 있다고 생각한다.도와줘서 고마워요!
학습을 계속하려면 다음 예제를 참조하십시오.

https://github.com/shawnwildermuth/vuejwt


최소 ASP.NET Core 프로젝트는 두 개의 API를 공개했습니다(하나는 인증용, 다른 하나는 색조 반환용).인증을 수행하면 JWT만 반환됩니다.
[HttpPost]
public ActionResult<AuthResultModel> Post([FromBody] AuthRequestModel model)
{
  // NEVER DO THIS, JUST SHOWING THE EXAMPLE
  if (model.Username == "[email protected]"
    && model.Password == "P@ssw0rd!")
  {
    var result = new AuthResultModel()
    {
      Success = true
    };

    // Never do this either, hardcoded strings
    var token = TokenSecurity.GenerateJwt(model.Username);
    result.Token = new JwtSecurityTokenHandler().WriteToken(token);
    result.Expiration = token.ValidTo;

    return Created("", result);

  }

  return BadRequest("Unknown failure");
}

Vue 섹션의 최소 JWT 구현을 테스트할 뿐이므로 서버 코드를 예로 사용하지 마십시오.
클라이언트 디렉토리에 Vue 3 항목이 있습니다.이것이 바로 우리가 주목해야 할 곳이다.우선 로그인 페이지가 필요합니다.
<template>
  <div>
    <h1>Login</h1>
    <form novalidate @submit.prevent="onSubmit()">
      <div class="form-group">
        <label for="username">Username</label>
        <input type="text" name="username" v-model="model.username" class="form-control" />
      </div>
      <div class="form-group">
        <label for="password">Password</label>
        <input type="password" name="password" v-model="model.password" class="form-control" />
      </div>
      <div class="form-group">
        <input type="submit" class="btn btn-success" value="Login" /> 
        <router-link class="btn btn-info" to="/">Cancel</router-link>
      </div>
    </form>
  </div>
</template>

<script>
  import { reactive } from "vue";
  import store from "@/store";

  export default {
    setup() {

      const model = reactive({ username: "", password: ""});

      function onSubmit() {
        store.dispatch("login", model);
      }

      return {
        model,
        onSubmit
      }
    }
  }
</script>

이 모든 것은 우리의 모델을 채택하고 이를 Vuex에 보내서 실제 인증을 하는 것입니다.이것은 단지 간단한 형식일 뿐이다.모든 진정한 마법은 Vuex 상점에 있습니다.
actions: {
  login: async ({ commit }, model) => {
    try {
      commit("setBusy");
      commit("clearError");
      const http = createHttp(false); // unsecured
      const result = await http.post("/api/auth", model);
      if (result.data.success) {
        commit("setToken", result.data);
        router.push("/");
      }
      else {
        commit("setError", "Authentication Failed");
      }
    } catch {
      commit("setError", "Failed to login");
    } finally {
      commit("clearBusy");
    }
  },
}

이 동작에서, 나는 단지post와 사용자 이름/비밀번호로 서비스를 호출할 뿐이다.만약 성공한다면, 나는 영패를 저장할 것이다. (Vuex에도 저장할 것이다.)토큰의 실제 저장, 토큰, 만료 설정:
  mutations: {
    // ...
    setToken: (state, model) => {
      state.token = model.token;
      state.expiration = new Date(model.expiration)
    }
  },

그리고 getter가 로그인 여부를 되돌려줍니다.
  getters: {
    isAuthenticated: (state) => {
      return state.token.length > 0 &&
        state.expiration > Date.now();
    }
  }, 

getter는 우리가 영패가 있는지, 기한이 지났는지 테스트하고 있습니다.만기가 다가오면서 다시 로그인할 수 있는 신기한 방법은 없다.Vuex 객체에 자격 증명을 저장하여 재검증하지 않는 것이 좋습니다. 이는 상당한 보안 취약점입니다.다음 사용자가 필요할 때, 나는 로그인 페이지로 방향을 바꿀 뿐이다.그러나 이 가설은 사실상 당신의 특정한 용례를 바탕으로 한다.서버에서 인증된 호출마다 만료 시간을 미끄러뜨릴 수 있지만 보안이 높은 상황에서 사용해서는 안 됩니다.
지금 우리는 로그인하는 방법이 생겼는데, 우리는 어떻게 해야 합니까?이것이 바로 루트의 용무지이다.다음과 같은 간단한 라우팅 세 페이지(로그인 포함)가 있습니다.
const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/colors',
    name: 'Colors',
    component: Colors,
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  },
]

그러나 일부 페이지가 인증되지 않으면 보호해 주십시오.우리가 이 점을 할 수 있는 것은 마치 수비수와 같다.보호는 루트 파이프 기간에 실행되는 작은 코드입니다.예를 들어, 라우팅을 실행하기 전에 라우팅을 실행하고자 합니다.
const authGuard = (to, from, next) => {
  if (store.getters.isAuthenticated) {
    next();
  } else {
    next("/login")
  }
};

이 방법은 루트의 목적지, 출처, 그리고 최종 호출된 함수 (next) 를 가져와 루트를 호출하거나 다시 호출합니다.우리의 예에서, 만약 그것이 신분 검증을 거쳤다면, 우리는 다음 것을 호출하여 원하는 곳으로 이동할 수 있을 뿐이다.그러나 그렇지 않으면 로그인 페이지로 다시 지정합니다.일단 우리가 이 함수를 가지게 되면 우리는 그것을 필요한 경로에 적용할 수 있다.
  {
    path: '/colors',
    name: 'Colors',
    component: Colors,
    beforeEnter: authGuard
  },

이렇게 하면 인증 전에 "색상"을 입력하면 로그인 페이지로 다시 라우팅됩니다.이 예는 로그인 후 색을 바꾸는 문제를 처리하지 않았지만, 쉽게 할 수 있습니다.제 예에서는 로그인할 때마다 Vue 프로젝트의 루트로 리디렉션합니다.
const result = await http.post("/api/auth", model);
if (result.data.success) {
  commit("setToken", result.data);
  router.push("/");
}

router.push("/")>에 대한 호출은 방향을 바꾸는 작용이다.
알겠습니다. 로그인하지 않은 사람이 방문하지 않도록 경로가 보호되었습니다. 하지만 지금 우리는 JWT 영패를 어떻게 사용합니까?이 예에서, 나는axios를 네트워크에 사용할 것입니다. (그러나fetch를 사용하여 유사한 작업을 할 수 있습니다.)이 예에서 나는 내가 사용하는 http 대상을 구축하는 함수를 가지고 있다.
import axios from "axios";
import store from "@/store";

export default function createHttp(secured = true) {

  if (secured) {
    return axios.create({
      headers: { "Authorization": `bearer ${store.state.token}` }
    });
  } else {
    return axios.create();
  }
} 

createHttp를 호출할 때 매개 변수 (또는true) 가 없으면 저장소에서 권한 부여 헤더를 자동으로 추가합니다.그렇지 않으면, 나는 하나만 만들 것이다.왜 우리 둘 다 필요해?응, 안전하지 않은 것은 사실상 로그인에 필요한 거야.이것이 바로 기본 설정이 보안 연결을 만드는 이유입니다.
이 최소한의 예시가 당신의 Vue 프로젝트에서 영패를 사용할 수 있기를 바랍니다.만약 당신이 개선 예시를 보았다면 저에게 (또는 직접 저에게 PR을 주세요.)

Shawn Wildermuth의 이 작품은 Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License에 따라 허가를 받았다.
wildermuth.com 기반 작업.
이 글을 좋아하신다면 Shawn 강의 Pluralsight 를 참조하십시오.

좋은 웹페이지 즐겨찾기