MY MEMO
[IONIC+Django] 로그인, 회원가입을 위한 Token Authentication 본문
+) https://www.youtube.com/watch?v=0jSzFUZ__k8 이 유튜브 강의에 매우 자세하고 완벽하게 나와있다
따라하기만 하면 가능하기 때문에 그대로 하면 된다
(Token Authentication 관련 동영상은 29,31,32이다!)
+) User 테이블을 생성하지 않아도 default 테이블이 존재한다 (AbstratUser)
하지만 새로 정의해줘도 괜찮다
models.py
: AbstractUser가 Django에 있는 기본 테이블이다
그 테이블을 상속시켜주고 username을 Email Field로 변경했다 (변경을 해주지 않아도 괜찮다)
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
username = models.EmailField(unique=True, null=False, max_length=254)
admin.py
: localhost:8000/admin에 보이기 위해서 admin.py를 변경한다
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'password','email','is_superuser')
admin.site.register(User, UserAdmin)
Setting.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework.authentication.BasicAuthentication',
# 'rest_framework.authentication.SessionAuthentication',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
'DEFAULT_RENDERER_CLASSES': (
# 자동으로 json으로 바꿔줌
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
),
# 기본적인 permission 정의 가능
'DEFAULT_PERMISSION_CLASSES':(
'rest_framework.permissions.IsAuthenticated',
)
}
AUTH_USER_MODEL = 'api.User'
JWT : Json Web Token
=> pip install jwt
IsAuthenticated : 기본적인 Permission 정의
(즉 permission_classes를 정의하지 않으면 DEFAULT_PERMISSION_CLASSES안에 있는 권한이 기본 권한으로 정의된다)
AUTH_USER_MODEL = Application이름.User테이블의 이름
serializers.py
from rest_framework import serializers
from ..models import BlogPost, User
from django.core.validators import ValidationErrorfrom django.db.models import Q
class UserCreateSerializer(serializers.HyperlinkedModelSerializer):
def create(self, validated_data):
username = validated_data['username']
email = validated_data['email']
password = validated_data['password']
user_obj = User(
username = username,
email = email
)
user_obj.set_password(password)
user_obj.save()
return validated_data
class Meta:
model = User
fields = [
'username',
'password',
'email',
'is_superuser',
]
class UserLoginSerializer(serializers.ModelSerializer):
token = serializers.CharField(allow_blank=True,read_only=True)
username = serializers.EmailField(required=False, allow_blank=True)
email = serializers.EmailField(label='Email Address',required=False, allow_blank=True)
class Meta:
model = User
fields = [
'username',
'email',
'password',
'token',
]
extra_kwargs = {'password':{"write_only":True}}
def validate(self, data):
email = data.get("email", None)
username = data.get("username", None)
password = data.get("password",None)
if not email and not username :
raise ValidationError("A username and email is required to login")
user = User.objects.filter(
Q(email=email)|
Q(username=username)
).distinct()
if user.exists() and user.count() == 1:
user_obj = user.first()
else:
raise ValidationError("A username/email is not valid")
if user_obj:
if not user_obj.check_password(password):
raise ValidationError("Incorrect credentials please try again")
return data
views.py
: permission_classes = [AllowAny] : 모두 허가한다
UserRegisterAPIView에서 ListCreateAPIView를 이용하면 /register를 했을 때 모든 계정의 비밀번호와 아이디를 볼 수 있다
하지만 이는 보안이 약해질 우려가 있기 때문에 generics.CreateAPIView로 변경해주는 것이 보안에 편하다
아래는 좀 더 편하게 개발하기 위해 ListCreateAPIView를 이용하여 구현하였다
class UserRegisterAPIView(generics.ListCreateAPIView):
serializer_class = UserCreateSerializer
permission_classes = [AllowAny]
queryset = User.objects.all()
class UserLoginAPIView(APIView):
# post를 하기 때문에 localhost:8000/api/test/login 으로 데이터를 확인할 수 없음
# localhost:8000/api/test/login으로 확인하기 위해서는!
serializer_class = UserLoginSerializer
permission_classes = [AllowAny]
def post(self, request, *args, **kwargs):
data = request.data
serializer = UserLoginSerializer(data=data)
if serializer.is_valid(raise_exception=True):
new_data = serializer.data
return Response(new_data, status=HTTP_200_OK)
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
urls.py
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
url(r'^api-token-auth/', obtain_jwt_token), # Token을 가져오는 url
url(r'^register/', UserRegisterAPIView.as_view(),name='register'),
url(r'^login/', UserLoginAPIView.as_view(),name='login')
]
Login Api
: username 이나 email을 입력했을 경우 로그인이 가능
register api
: 비밀번호는 set_password 즉 hash를 이용해서 변경
Postman으로 Token을 확인했을 때
: body에서 username이나 password를 입력해서 token을 얻을 수 있음
'STUDYING > APPLICATION' 카테고리의 다른 글
[IONIC+Django] api를 이용해 데이터 가져오기 (0) | 2018.01.23 |
---|---|
[IONIC] ionic 설치하기 (0) | 2018.01.16 |
[ANDROID] 안드로이드에서 MAVEN 추가 (MAC) (0) | 2017.12.05 |
[ANDROID] ListView 만들기 (0) | 2017.12.03 |