본문 바로가기

Web/Django

[Django, React] 로그인, 회원가입 연동 (2)

회원가입에서는 토큰을 생성하지 않고 걍 입력받은 유저 정보만 장고로 넘겨줌

 

React의 signup.js

const data = { username, password };
      try {
        await Axios.post("http://localhost:8000/accounts/signup/", data);
        notification.open({
          message: "회원가입 성공",
          description: "로그인 페이지로 이동합니다.",
          icon: <SmileOutlined style={{ color: "#108ee9" }} />,
        });

 

로그인 시 토큰 생성

 

React의 login.js

  const onFinish = (values) => {
    async function fn() {
      const { username, password } = values; #form에서 받아온 입력값

      const data = { username, password };
      try {
        const response = await Axios.post(
          "http://localhost:8000/accounts/token/",
          data
        );
        console.log("response: ", response.data);

        setToken(response.data);

        setStorageItem("username", username);
        console.log("access_token: ", response.data['access']);

        notification.open({
          message: "Login SUCCESS",
          icon: <SmileOutlined style={{ color: "#108ee9" }} />,
        });

        navigate("/");
      }

 

Django의 urls.py

urlpatterns = [
    path('signup/', views.SignupView.as_view(), name='login'),
    path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

 


  • 라이브러리 내부 코드
  • TokenObtainPairView 동작 과정; 내장된 검증 로직 존재

.../rest-framework-simplejwt/views.py

class TokenObtainPairView(TokenViewBase):
    """
    Takes a set of user credentials and returns an access and refresh JSON web
    token pair to prove the authentication of those credentials.
    """

    _serializer_class = api_settings.TOKEN_OBTAIN_SERIALIZER


token_obtain_pair = TokenObtainPairView.as_view()

.../rest-framework-simplejwt/serializers.py

class TokenObtainSerializer(serializers.Serializer):
    username_field = get_user_model().USERNAME_FIELD # settings에서 설정한 모델 필드 불러오고
    token_class: Optional[Type[Token]] = None

    default_error_messages = {
        "no_active_account": _("No active account found with the given credentials")
    }

    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)

        self.fields[self.username_field] = serializers.CharField(write_only=True)
        self.fields["password"] = PasswordField()

	# 검증 로직
    def validate(self, attrs: Dict[str, Any]) -> Dict[Any, Any]:
        authenticate_kwargs = {
            self.username_field: attrs[self.username_field],
            "password": attrs["password"],
        }
        try:
            authenticate_kwargs["request"] = self.context["request"]
        except KeyError:
            pass

        self.user = authenticate(**authenticate_kwargs)

        if not api_settings.USER_AUTHENTICATION_RULE(self.user):
            raise exceptions.AuthenticationFailed(
                self.error_messages["no_active_account"],
                "no_active_account",
            )

        return {}

    @classmethod
    def get_token(cls, user: AuthUser) -> Token:
        return cls.token_class.for_user(user)  # type: ignore


class TokenObtainPairSerializer(TokenObtainSerializer):
    token_class = RefreshToken

    def validate(self, attrs: Dict[str, Any]) -> Dict[str, str]:
        data = super().validate(attrs)

        refresh = self.get_token(self.user)

        data["refresh"] = str(refresh)
        data["access"] = str(refresh.access_token)

        if api_settings.UPDATE_LAST_LOGIN:
            update_last_login(None, self.user)

        return data

 

=> login.js 파일에서 장고의 /token 경로로 입력한 username, password 값을 넘겨줌

=> TokenObtainPairView로 연결되어 내장된 검증 로직으로 입력값을 검증 후 토큰 생성