Mini Project|暗号化および認証トークンの発行:


会員入力/登録エンドポイントの最終ステップ-認証、承認実施


1.bcrypt暗号化


パスワードの暗号化はプライバシーの鍵です
bcryptはstring(문자열)データを暗号化し、Bytes(이진화)データではない.
ユーザ登録会員のパスワードはstringであるため、パスワードをBytesに変換して暗号化する必要がある.
  • encode : str > Bytes
  • decode : Bytes > str
  • 符号化、復号時に「utf-8」Unicode文字仕様
  • を使用

    インストール
  • bcrypt
  • pip install bcrypt
  • 暗号暗号化実験
  • import bcrypt		# bcrypt 라이브러리 import
    
    password = '1234'	
    type(password)
    <class 'str'>		# 입력된 비밀번호 타입: string(문자열)
    
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())	# 비밀번호 암호화
    type(hashed_password) 
    <class 'bytes'>		# 암호화된 비밀번호 타입: bytes
    
  • 暗号解読実験
  • new_pw = '1234'
    bcrypt.checkpw(new_pw.encode('utf-8'), hashed_password)
    ここでnew pwencode(「utf-8」)は、ユーザがログインしたときに入力したパスワードです.
    hashed passwordは格納された暗号化パスワードです.

    登録およびログインに適用するコスト

    import bcrypt		# bcrypt import
    
    # 회원가입(signup)
    class SignupView(View):
    	def post(self, request):
        		data = json.loads(request.body)
    
    		email_validation = '^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
            	pw_validation = '^[A-Za-z0-9@#$%^&+=]{8,}$'
                
                	try:         
                    	if not re.match(email_validation, data['email']):
      				return JsonResponse(
      					{"message":"INVALID_ID"}, status = 401
    					)
                    
                    	if not re.match(pw_validation, data['password']:
    				return JsonResponse(
                                            {"message":"INVALID_PW"}, status = 400
                                            )
    
                            if Users.objects.filter(email=data['email']).exists():
    				return JsonResponse(
    					{"message":"USER_EXIST"}, status = 400
    					)
    
    		else:	 # 에러 발생시키지 않는 경우 이메일, 암호화된 비밀번호를 다시 string으로 변환해 저장
    			Users.objects.create(
    				email = data['email'],
    				password = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
    				).save()
     
    			return JsonResponse({'message': 'SUCCESS'}, status = 
     
    		except KeyError:
    			return JsonResponse({"message":"KEY_ERROR"}, status = 400)
    
    
    # 로그인(signin)
    class SigninView(View):
    	def post(self, request):
    		data = json.loads(request.body)
    
    		try:
    			if Users.objects.filter(email=data['email']).exists():
    				user = Users.objects.get(email=data['email'])
    
    				# 암호화된 비밀번호 복호화해서 저장되어 있는 비밀번호와 비교, 동일하면 success 반환
    				if bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8')):
    
    					return JsonResponse({"message":"SUCCESS"}, status = 200)
    			
                			return JsonResponse({"message": "INVALID_PW"}, status = 401)
                            
    		else:
    			return JsonResponse({"message":"INVALID_USER"}, status = 401)
    		
            	except KeyError:
    			return JsonResponse({"message":"KEY_ERROR"}, status = 400)
    

    2.JSON Web Tokenの発行


    JWTによるユーザー認証の実装
    インストール
  • pyjwt
  • pip install pyjwt		# pyjwt 설치
  • jwt発行実習
  • import jwt			# jwt import
    
    SECRET = 'secret'		# settings.py 에 들어있는 secret key
    
    access_token = jwt.encode({'id':1}, SECRET, algorithm='HS256')
    # user(id=1)에 대한 Token 발행

    ログイン時のトークンの発行と返却

    import jwt		# jwt import
    
    from my_settings import SECRET	# my_settings에 있는 SECRET key 참조
    
    # 로그인 view
    class SigninView(View):
    	def post(self, request):
    		data = json.loads(request.body)
    
    		try:
    			if Users.objects.filter(email=data['email']).exists():
    				user = Users.objects.get(email=data['email'])
    
    				if bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8')):
    					
                        			access_token = jwt.encode({'id'=user.email}, SECRET, algorithm = 'HS256').decode('utf-8')
    					
                        			return JsonResponse({"message":"SUCCESS", "Token": access_token}, status = 200)
    			
                			return JsonResponse({"message": "INVALID_PW"}, status = 401)
                            
    		else:
    			return JsonResponse({"message":"INVALID_USER"}, status = 401)
    		
            	except KeyError:
    			return JsonResponse({"message":"KEY_ERROR"}, status = 400)
    暗号化は、JWTが概念を理解するだけでそれほど難しくなく、すぐに実現します.
    最初から暗号化、JWTが実現できれば、コードを書くことも考えられるはずですが、今後の応用のためには、最初に書いたコードを修正し続ける必要があるので、その過程でいろいろ考え、勉強にも少し進歩しました.
    これにより、暗号化およびJWTを含む登録およびログインページの実装が完了します:)