Django_9)Authentication System

지비지비집·2023년 11월 1일
0

Django

목록 보기
9/14
post-thumbnail

중요한 내용을 배우기 전에 이야기를 한 번 해보자.
우리는 웹 서비스를 개발할 때에, 여러 기능이 필요할 것이다.
Instagram을 개발한다고 할 때 어떤 기능을 더 구현해야할까? 우리는 충분히 글과 그림의 게시글을 작성, 조회, 수정, 삭제 등을 할 수 있다. 이런 기능의 근본적인 목적은 사람들간 소통을 하기 위함이다. 팔로우 기능, 좋아요 기능, 댓글 기능까지도 구현해보려 한다. 그 전에 우리는 User라는 사용자 객체를 만들어 DB에 저장하고, 로그인 기능을 먼저 구현해야할 것이다.

HTTP

HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 규약
비 연결 지향 : 서버는 요청에 대한 응답을 보낸 후 연결을 끊음
무상태 : 연결을 끊는 순간 클라이언트와 서버 간의 통신이 끝나며 상태 정보가 유지되지 않음

쿠키 : 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각
세션 : 서버 측에서 생성되어 클라이언트와 서버 간의 상태를 유지, 상태 정보를 저장하는 데이터 저장 방식

쿠키의 사용 목적

  1. 세션 관리 : 로그인, 아이디 자동완성, 공지 하루 안 보기, 팝업 체크, 장바구니 등의 정보 관리
  2. 개인화 : 사용자 선호, 테마 등의 설정
  3. 트래킹 : 사용자 행동을 기록 및 분석

세션 작동 원리

  1. 클라이언트가 로그인 하면 서버가 session data 생성 후 저장
  2. 생성된 session data에 인증할 수 있는 session id 발급
  3. 발급한 session id를 클라이언트에게 응답
  4. 클라이언트는 응답 받은 session id를 쿠키에 저장
  5. 클라이언트가 다시 동일한 서버에 접속하면 요청과 함께 쿠키를 서버에 전달
  6. 쿠키는 요청 때마다 서버에 함께 전송되므로 서버에서 session id를 확인해 로그인 되어있다는 것을 알도록 함

쿠키와 세션의 목적은 결국 서버와 클라이언트 간의 상태를 유지하기 위함이다.
이젠 계정을 관리하는 앱을 만들어보자.

$ python manage.py startapp accounts
# 이후 앱 등록 + urls 연결까지 진행

이제는 Django의 권장사항을 하나 따라야 하는데, Django에서 기본적으로 제공하는 User model을 Custom해야한다. 그 이유는 내장 User model은 auth에 내장된 User 클래스를 사용하는데 이는 우리가 원하는 column을 이후에 변경하거나 추가하기 힘들기 때문에 최초에 CustomUsermodel을 만들어야한다. 결국 최초 언급했던 우리가 framework 덕분에 편하게 유저에 대한 데이터를 다룰 수 있지만 직접 수정할 수 없는 문제도 있다는 것이다. 그럼 어떻게 커스텀 하는지 알아보러 가보자.

  1. 모델 설정

  2. 프로젝트 전체에서 바라보는 유저 바꾸기(auth.User -> accounts.User)

  3. 관리자 페이지에서 User 만들 수 있도록 설정

우린 처음에 Django에서 기본적으로 제공하는 User는 사용해보기도 전에 커스텀해버렸다. 왜 그렇게 커스텀하는 것이 중요할까? -> 프로젝트 중간에는 AUTH_USER_MODEL을 변경할 수 없다. 이미 프로젝트가 진행되고 있다면? -> DB를 초기화 한 이후 진행해야한다.

로그인(Login)

Session을 Create하는 과정

AuthenticationForm()

로그인 인증에 사용할 데이터를 입력받는 built-in form



CRUD 과정에서 익숙한 형태의 코드일테지만 views.py의 내용은 중요하고 많다보니 같이 들여다보자. 우리는 로그인이라는 기능 또한 django의 auth가 제공하는 기능을 사용할 것이니 login이라는 것을 import 받는데 우리는 login이라는 이름의 view 함수를 사용할 것이므로 이름을 auth_login으로 수정하며 시작하자. 유저의 입장에서 로그인이라는 페이지로 들어오면 이는 GET 요청으로 비어있는 AuthenticatedForm을 제공할 것이다. 그럼 유저는 빈 폼에 아이디와 비밀번호 정보를 입력하여 제출을 할 것이며 이는 POST요청이 될 것이다. 그럼 입력받은 정보를 담은 폼을 유효성 검사를 거친 후 로그인을 시키는데 이때, 필요한 인자는 request와 form.get_user() 2개이다. 그리고 로그인 완료 되었으면 INDEX 페이지로 돌려보내자.

login(request, user)

AuthenticationForm 을 통해 인증된 사용자를 로그인하는 함수
get_user() : AuthenticationForm의 인스턴스 메서드로, 유효성 검사를 통과했을 경우, 로그인한 사용자 객체를 반환
view함수의 이름과 겹치지 않도록 주의(재귀 오류) -> 위에선 auth_login으로 바꿈

로그아웃(Logout)

Session을 Delete하는 과정

logout(request)

현재 요청에 대한 Session Data를 DB에서 삭제, 클라이언트의 쿠키에서도 Session Id를 삭제
view함수의 이름과 겹치지 않도록 주의(재귀 오류) -> auth_logout으로 이름 바꾸기

회원가입

User객체를 Create 하는 과정

UserCreationForm()

회원가입시 사용자 입력 데이터를 받을 built-in ModelForm

로그인에서는 분명 built-in form을 사용했는데 왜 회원가입은 ModelForm을 사용하는가?
우리가 처음 ModelForm을 학습할 당시를 떠올려보면 그 기준이 생각날 것이다. 로그인이라는 과정은 조회에 해당하지만 회원가입은 생성에 해당하여 DB에 저장해야할 것이다. 이렇게 DB에 영향을 주는 기능은 ModelForm을 활용하기로 했었다.



의 코드 해석은 여러분께 맡긴다. 주목할 점은 UserCreationForm은 1개의 변수만을 갖는다.
그리고 DB에 저장하는 과정도 거치게 된다. 그렇게 회원가입을 진행하게 되면?


이러한 오류가 발생하게 된다. 읽어보면 우리가 바꾼 User모델인 CustomUsermodel이 아닌 기존 Usermodel을 참조하고 있다고 한다. 생성 과정과 우리가 아직 만들지 않았지만 수정 과정은 ModelForm을 사용하기 때문에 이는 자동으로 Meta 클래스에서 User를 참조하고 있으므로 Custom을 통해 Meta의 model을 수정해야한다.


수정하고 views.py에서도 수정을 진행하면 또 다른 문제에 봉착한다.

회워가입에서 볼 수 없는 옵션들도 유저에게 하여금 선택가능하다. 이는 제제를 할 필요가 있어보인다. 필요한 fields만 남겨두자. 비밀번호는 따로 관리하므로 넣지 않아도 자동으로 만들어준다.

이정도면 충분한 것 같다. 위에서 get_user_model()로 우리는 모델을 참조하고 있다 분명 models.py에서 정의한 User 클래스를 써도되고, settings.py의 AUTH_USER_MODEL을 참조해도 되지만 이 또한 권장사항으로 get_user_model()을 사용하자 이는 메서드이므로 괄호를 붙여야 한다. 정확한 의미는 "현재 프로젝트에서 활성화된 사용자 모델"을 반환하는 함수이다.

회원탈퇴

User 객체를 Delete 하는 과정



한 가지만 언급하고 넘어가겠다. POST 요청 보내는 request에 담겨있는 회원 정보를 지우고 싶다면 request.user로 접근하면 된다.

회원정보 수정

UserChangeForm()

회원정보 수정 시 사용자 입력 데이터를 받을 built-in ModelForm




게시글의 수정과 비슷하게 instance 인자를 사용하고 있는 모습이고, ModelForm에 대한 설정을 다시 보자면 비밀번호 수정을 넣지 않았다. 하지만 수정을 들어가보면 비밀번호 수정란이 뜨는 것을 볼 수 있다. 이는 Django에서 따로 관리하기 때문인데 수정을 하면 Error 화면을 보여준다. 이를 해결하러 가보자.

비밀번호 변경

인증된 사용자의 Session Data를 Update하는 과정

PasswordChangeForm()

비밀번호 변경 시 사용자 입력 데이터를 받을 built-in Form



짚고 넘어가야할 내용은 2가지로 보인다. 첫째 비밀번호는 DB에 저장될까? 그렇다면 ModelForm일텐데? Form이네? 그렇다 비밀번호는 DB에 그대로 저장되지 않는다. 둘째는 비밀번호 변경에 대한 url은 project urls.py에 작성함을 볼 수 있다. 이를 주의하자.

추가로 혹시 비밀번호를 변경하면 기존 세션과의 정보가 달려저서 로그아웃 처리됨을 알 수 있는데 난 변경을 해도 로그아웃 상태를 유지하고 싶다고 한다면 update_session_auth_hash 메서드를 사용해볼 수 있다.

그렇다면 우리는 User에 대한 긴 학습을 마쳤고 뿌듯한 마음으로 index 홈페이지로 들어가보자.
로그인, 로그아웃, 회원가입, 회원정보 수정, 회원탈퇴 등을 해보면 혹시 이상한 점이 있지 않은가? 가장 불편한 점은 내가 로그인이 되어있는지 아닌지를 알 수 없으며, 로그인을 해도 로그인 창을 들어갈 수 있고, 회원가입 창을 갈 수 있으며, 로그아웃 상태에서도 회원탈퇴 버튼이 보이고 있다. 이를 어떻게 해결할 수 있을까? 적어도 내가 로그인 상태인지 아닌지 정도는 구분하고 싶다. 여기엔 2가지 방법이 있다.

is_authenticated 속성

사용자가 인증 되었는지 여부를 알 수 있는 User model의 속성
모든 User 인스턴스에 대해 항상 True인 읽기 전용 속성이며, 비인증 사용자에 대해서는 항상 False


DTL의 조건문을 활용하여 로그인 상태 여부를 간접적으로 확인할 수 있도록 설정. 하지만 url로 접근하는 것은 막을 수 없기 때문에 한 가지 조건을 더 달아주자.

login_required 데코레이터

인증된 사용자에 대해서만 view 함수를 실행시키는 데코레이터
비인증 사용자의 경우 /accounts/login/ 주소로 redirect 시킴


긴 시간동안 한 번에 User를 어떻게 model을 정의하고 CRUD 하는지에 대해 알아보았다. 게시글의 CRUD와 코드는 비슷하지만 차이점도 분명 존재하였기 때문에 외우려하기보단 코드를 이해하려는 공부를 하는 것이 좋을 것이다. 이후에는 좋아요기능, 댓글기능, 팔로우 기능 등을 알아보도록 하자.

profile
"정말 무엇인가를 이해한다면 전문용어를 모르는 사람에게도 설명할 수 있어야 한다." -리처드 파인만-

0개의 댓글