[westagram] 회원가입 & 로그인

do yeon kim·2022년 7월 13일
0

회원가입 흐름

회원가입시 클라이언트와 서버사이에 어떤 흐름이 발생하는가?

  • 클라이언트에서 회원가입에 대한 정보가 보내진다.
    이메일, 패스워드, 개인정보 등
    http통신을 통해 json형태로 데이터가 보내진다.

  • 서버측에서 파이썬이 사용가능한 형태로 데이터를 변환시킨다.
    json.loads()를 이용해서 딕셔너리 형태로 변환시킨다.
    여기서 키값이 올바르게 들어오지 않은 경우 keyerror가 발생한다.

  • 각각의 데이터에 대한 오류확인을 후 이상이 없을 시 데이터베이스에 저장한다.

  • 서버 측에서 클라이언트 측에 성공메시지를 보낸다.



로그인 흐름

  • 클라이언트 측에서 아이디와 패스워드를 http통신을 이용해서 보낸다.

  • 서버에선 들어온 정보와 데이터베이스에 저장된 정보가 같은지 판단한다.

  • 같다면 로그인 성공, 틀리다면 오류를 발생시킨다.



클라이언트와 서버의 연결

아직 우리는 도메인을 가지고 있지 않다.
그러므로 서버측의 IP Address를 클라이언트 측에 알려주어 접속을 하게 한다.

  • ipconfig getifaddr en0 맥에서 자신의 무선 아이피 주소를 확인
  • ipconfig getifaddr en0 맥에서 자신의 유선 아이피 주소를 확인
  • Curl ifconfig.me 맥에서 자신의 public IP Address 확인

예시)
http://아이피 주소:포트번호/프로젝트url주소/앱usl주소
회원가입
http://10.5.123.12:8000/user/signup
로그인
http://10.5.123.12:8000/user/login

클라이언트 쪽에서 위에 예시로 들은 아이피 주소로 접속시 서버가 열려있다면 작업이 가능하다.



모델링 user/models.py

from django.db import models

class User(models.Model):
    name         = models.CharField(max_length=100)
    email        = models.CharField(max_length=100, unique=True)
    password     = models.CharField(max_length=100)
    phone_number = models.CharField(max_length=100, unique=True)
    create_at    = models.DateTimeField(auto_now_add=True)
    update_at    = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'users'
  • 사용할 테이블에 대한 모델링을 해준다.



회원가입 user/viesw.py/UserView()


class UserView(View):
    def post(self, request):
        try:
            data              = json.loads(request.body)

            name              = data["name"]
            email             = data["email"]
            password          = data["password"]
            phone_number      = data["phone_number"]

            regx_email        = '^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
            regx_password     = '^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$'
            regx_phone_number = '^\d{3}-\d{3,4}-\d{4}$'

  • json.loads(request.body)를 이용해서 http통신 시 post를 통해 들어오는 request의 json데이터를 파이썬에 맞는 딕셔너리 형태로 변경해준다.

  • data["키"]를 이용해서 키에 대한 값을 변수에 저장한다.

  • 정규식에 해당하는 패턴을 정의해 준다.

            check_email_regx(regx_email, email)

            if User.objects.filter(email = email).exists():
                raise ValueError("EXISTED_EMAIL")

            check_password_regx(regx_password, password)
            check_phone_regx(regx_phone_number, phone_number)
            
            if User.objects.filter(phone_number = phone_number).exists():
                raise ValueError("EXISTED_PHONE-NUMBER")

  • 정의한 함수와, filter()를 이용해서 정확한 데이터인지를 판단해준다.

            hashed_password  = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

  • 데이터 베이스에 저장할 패스워드를 보안과 개인정보 보호를 위해 암호화해서 저장한다.

            User.objects.create(
                name         = name,
                email        = email,
                password     = hashed_password,
                phone_number = phone_number,
            )

            return JsonResponse({"message": "SUCCESS"}, status=201)

  • 이곳 까지 내려오면 데이터에 대한 유효성 검사가 완료 된 상태로, 데이터로 새로운 User객체를 생성해 준다.(회원가입을 완료한다)

        except KeyError:
            return JsonResponse({"message": "KEY_ERROR"}, status=400)
        except ValueError as e:
            return JsonResponse({"message": f"{e}"}, status=400)

  • 에러에 대한 처리이다.
def check_email_regx(pattern, field_data):
    if not re.compile(pattern).match(field_data):
        raise ValueError("INVILD_EMAIL")

def check_password_regx(pattern, field_data):
    if not re.compile(pattern).match(field_data):
        raise ValueError("INVILD_PASSWORD")

def check_phone_regx(pattern, field_data):
    if not re.compile(pattern).match(field_data):
        raise ValueError("INVILD_PHONE-NUMBER")

  • 각 데이터에 대한 정규식 확인을 함수로 정의했다.

로그인 user/viesw.py/LoginView()

로그인을 하기 위해서는 로그인에 대한 정보가 들어있는 데이터베이스와 서버가 통신을 해서 아이디와 비밀번호를 가지고 오고, 클라이언트로 부터 http통신을 통해 json으로 들어온 데이터의 아이디와 비밀번호가 같은지 판단을 해서, 그 결과를 응답해 주면 된다.

만약 로그인에 성공한 경우 response에 토큰을 함께 보내서, 통신의 stateless 속성에 대해서 이후에도 통신이 가능하게 한다.

class LoginView(View):
    def post(self, request):
        try:
            data     = json.loads(request.body)

            email    = data["email"]
            password = data["password"]

  • json.loads로 request의 body에 들어온 아이디와 비밀번호를 딕셔너리 형태로 변경해서 변수에 저장해준다.
            user     = User.objects.get(email = email)

            if not bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8')):
                return JsonResponse({"message": "INVILD_USER"}, status=400)

            access_token = jwt.encode({"id": user.id}, settings.SECRET_KEY, settings.ALGORITHM)

            return JsonResponse({
                "message": "SUCCESS",
                "access_token": access_token
            }, status=200)

  • get()함수를 이용해서 해당 유저를 변수에 저장해준다.

  • 패스워드 저장시 hash로 저장된 데이터를 유저에게서 들어온 패스워드를 비교해준다.

  • 만약 패스워드가 맞다면 jwt를 이용해서 토큰을 발급해준다.

  • jwt.encode({"id": user.id}, settings.SECRET_KEY, settings.ALGORITHM)

        except User.DoesNotExist :
            return JsonResponse({"message": "DOES_NOT_EXIST"}, status=401)
        except KeyError:
            return JsonResponse({"message": "KEY_ERROR"}, status=400)
  • 발생할 수 있는 에러 처리에 관한 부분이다.



westagram/urls.py

어느 app을 호출할 것인지를 결정해준다.


from django.urls import path, include

urlpatterns = [
   path("user", include("users.urls")),
]


user/urls.py

app 중에서 어느 view를 호출 할 것인지를 결정한다.

from django.urls import path

from .views import UserView, LoginView

urlpatterns = [
    path("/signup",UserView.as_view()),
    path("/login", LoginView.as_view()),
]


그 이외

위의 코드 이외에 westagram/settings.py에서 설정을 바꾸어 주어야 하며,
my_settings.py에서 시크릿키, 데이터베이스, 알고리즘 등의 설정도 이루어져야 한다.

0개의 댓글