[DRF] 카카오 로그인

애이용·2021년 2월 5일

django

목록 보기
4/4
post-thumbnail

📌 kakao login

Kakao Developers 에 자세한 구현 방법 확인할 수 있음!

views.py

이 문서를 토대로 작성한 코드

@api_view(['GET']) 
@permission_classes([AllowAny])
def oauth(request):
    code = request.GET['code'] 
    print('code = ' + str(code))

    secret_file = os.path.join(BASE_DIR, 'secrets.json')

    with open(secret_file) as f:
        secrets = json.loads(f.read())
    def get_secret(setting, secrets=secrets):
        try:
            return secrets[setting]
        except KeyError:
            error_msg = "Set the {} environment variable".format(setting)
            raise ImproperlyConfigured(error_msg)

    KAKAO_CLIENT_ID = get_secret("KAKAO_CLIENT_ID") # secrets.json에서 ID, Secret Key 받아옴
    #KAKAO_CLIENT_SECRET = get_secret("KAKAO_CLIENT_SECRET")

    redirect_uri = 'http://127.0.0.1:8000/user/login/kakao/callback'
    
    # request로 받은 code로 access_token 받아오기
    access_token_request_uri = 'https://kauth.kakao.com/oauth/token?grant_type=authorization_code&'
    access_token_request_uri += 'client_id=' + KAKAO_CLIENT_ID
    access_token_request_uri += '&code=' + code
    access_token_request_uri += '&redirect_uri=' + redirect_uri

    access_token_request_uri_data = requests.get(access_token_request_uri)
    json_data = access_token_request_uri_data.json() # json 형태로 데이터 저장
    access_token = json_data['access_token'] # 액세스 토큰 꺼내와서 저장

    # 프로필 정보 받아오기
    headers = ({'Authorization' : f"Bearer {access_token}"}) # header에 꼭 설정해야 함

    user_profile_info_uri = 'https://kapi.kakao.com/v2/user/me'
    user_profile_info = requests.get(user_profile_info_uri, headers=headers)

    json_data = user_profile_info.json() 

	# 닉네임과 이메일 데이터 가져옴
    nickname = json_data['kakao_account']['profile']['nickname']
    email = json_data['kakao_account']['email']
    
	# 데이터베이스에 이미 저장되어있는 회원이면, user에 회원 저장
    if User.objects.filter(email=email).exists():
        user = User.objects.get(email=email)
    # 회원가입인 경우
    else:
        user = User.objects.create(
            email=email,
            nickname=nickname
        )
        user.save()
	
    # 토큰 발행
    payload = JWT_PAYLOAD_HANDLER(user)
    jwt_token = JWT_ENCODE_HANDLER(payload)

    response = {
        'success' : True, 
        'token' : jwt_token
    }

    return Response(response, status=200)

📄 구현하면서


Objects: filter() vs get()

kakao login 시, 기존에 있는 email이면 로그인하고 없으면 회원가입 시킨 후, 로그인을 하게 된다.
이때 기존에 있는 회원인지 조건을 체크할 때 생긴 에러이다

처음에

user = User.objects.get(email=email)

이렇게 작성했다가 DoesNotExist라는 예외가 발생했다.
값이 없을 때 예외를 던지는 것이다

그래서 filter() 메서드의 exists() 로 조건을 체크했다
처음엔

user = User.objects.filter(email=email)
if user.exists():
    pass
else:
    user = User.objects.create(
   	   email=email,
           nickname=nickname
    )
    user.save()

payload = JWT_PAYLOAD_HANDLER(user)
jwt_token = JWT_ENCODE_HANDLER(payload)

filter를 통해 user을 저장하고, login되어있으면 pass 후, jwt_token을 생성하려고 했는데

payload = JWT_PAYLOAD_HANDLER(user

이 코드에서,

AttributeError: 'QuerySet' object has no attribute 'username'

이런 에러가 발생했다. 그래서 filter로 조건 체크하고, get()으로 user를 저장했다

if User.objects.filter(email=email).exists():
	user = User.objects.get(email=email)
    print('login')
else:
	user = User.objects.create(
    	   email=email,
           nickname=nickname
	)
    user.save()
    
payload = JWT_PAYLOAD_HANDLER(user)
jwt_token = JWT_ENCODE_HANDLER(payload)

이렇게 하면 성공적으로 로그인하고, 토큰도 발행 성공 !!


@api_view

Response 를 리턴할 때 @api_view(함수형 뷰) 어노테이션을 써야한다
없다면

AssertionError: .accepted_renderer not set on Response

이 에러 발생


key 관리

  • secrets.json

    .gitignore과 같은 위치에 생성
{
    "SECRET_KEY" : "~~",
    "KAKAO_CLIENT_ID" : "~~",
    "KAKAO_CLIENT_SECRET" : "~~"
}
  • settings.py

    secrets.json 파일 불러오기
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# SECURITY WARNING: keep the secret key used in production secret!
secret_file = os.path.join(BASE_DIR, 'secrets.json')

with open(secret_file) as f:
    secrets = json.loads(f.read())
def get_secret(setting, secrets=secrets):
    try:
        return secrets[setting]
    except KeyError:
        error_msg = "Set the {} environment variable".format(setting)
        raise ImproperlyConfigured(error_msg)

SECRET_KEY = get_secret("SECRET_KEY")
profile
로그를 남기자 〰️

0개의 댓글