swsnu / swppfall2019

31 stars 23 forks source link

[HW3] auth module 관련한 질문입니다. #176

Open GodDrinkTeJAVA opened 4 years ago

GodDrinkTeJAVA commented 4 years ago

고민하고 고민해도 답이 나오질 않아서 질문드립니다...

I found out I did not fully utilize the Django's in-built auth module, and I changed the code and auth problem comes out. The brief view of code is shown as below.

def signin(request):
    if request.method == 'POST':
        try:
            req_data = json.loads(request.body.decode())
            username = req_data['username']
            password = req_data['password']
            user = auth.authenticate(username=username, password=password)

            print(user) # this prints correct user

        except (KeyError, json.JSONDecodeError) as e:
            return HttpResponseBadRequest()

        if user is not None: # handles the case where user id is authenticated and returns 204

Here the print(with comment) shows that user is correctly input, and its username is shown as its str function assigns. Also, arc shows that login is successfully done and it gives 204 code.

However, when any other function, Django shows that request has no user in it and returns AnonymousUser. For example, getting list of articles shows

def article_list(request):
    is_login = request.user.is_authenticated
    print(request.user) # this prints anon

    if request.method == 'GET':
        if not is_login:
            return HttpResponse('Unauthorized', status=401)

When the print function with comment is called, AnonymousUser is called and thus, it returns 401.

More strange thing is, that arc shows the result as above, but python manage.py test(without CSRF checking except test_csrf function) gives OK sign after test.

What can be the reason for this phenomenon? Could be my use of ARC wrong? If someone with similar experience, please tell me why this happens...

zeroFruit commented 4 years ago

혹시 ARC로 Article을 조회할 때 session 정보도 같이 전달하셨나요?

zeroFruit commented 4 years ago

테스트케이스 코드도 공유해주시면 차이점을 파악하는데 도움이 될 거 같아요 👍

GodDrinkTeJAVA commented 4 years ago

    def setUp(self):
        test_user = User.objects.create_user(username="test", password="test")
        User.objects.create_user(username="another", password="another")
        test_article = Article.objects.create(title="test title", content="test content", author=test_user)
        Comment.objects.create(article=test_article, content="test comment", author=test_user)

    def test_get_article(self):
        client = Client()

        response = client.get('/api/article/')
        self.assertEqual(response.status_code, 401)

        client.post('/api/signin/', json.dumps({'username': 'test', 'password': 'test'}),
                        content_type='application/json')

        response = client.get('/api/article/')
        self.assertEqual(response.status_code, 200)
        self.assertIn('test title', response.content.decode())

        response = client.delete('/api/article/')
        self.assertEqual(response.status_code, 405)

이게 테스트코드입니다...

ktaebum commented 4 years ago

일단 지난 실습시간에 말씀드린 ARC session 정보에 ;까지 정확히 추가되었는지 signin 후에 csrf가 바뀐 것으로 다시 사용을 했는지 확인해보실 수 있나요?

zeroFruit commented 4 years ago

일단 저도 장고를 엄청 잘하는 것은 아니라 틀릴 수도 있지만

Client가 세션 정보를 가지고 있는 걸로 알고있습니다! Django client session으로 검색해보면 레펄런스가 나올거에요

제 추측으로 client가 세션 정보를 가지고 있기때문에 login이후의 리퀘스트가 제대로 동작할 수 있는게 아닌가 싶습니다

(모바일로 쓰느라 레퍼런스 주소를 못달아드려 죄송합니다)

GodDrinkTeJAVA commented 4 years ago

image image image image (other는 테스트상으로 만든 username입니다. 위의 print 부분에서 출력이 되고 있습니다)

ktaebum commented 4 years ago

145 와 같은 현상인 것 같은데요

혹시 signup을 별도로 고치셨는지, 고쳤으면 positional argument가 아니라 keyword argument로 제대로 넘겼는지도 확인해 보실 수 있나요?

GodDrinkTeJAVA commented 4 years ago

def signup(request):
    if request.method == 'POST':
        try:
            req_data = json.loads(request.body.decode())
            username = req_data['username']
            password = req_data['password']
        except (KeyError, json.JSONDecodeError) as e:
            return HttpResponseBadRequest()
        User.objects.create_user(username=username, password=password)
        return HttpResponse(status=201)
    else:
        return HttpResponseNotAllowed(['POST'])

def signin(request):
    if request.method == 'POST':
        try:
            req_data = json.loads(request.body.decode())
            username = req_data['username']
            password = req_data['password']
            user = auth.authenticate(username=username, password=password)

            print(user) # this prints correct user

        except (KeyError, json.JSONDecodeError) as e:
            return HttpResponseBadRequest()

        if user is not None:
            if user.is_active:
                auth.login(request, user)

                return HttpResponse(status=204)
        else:
            return HttpResponse('Unauthorized', status=401)
    else:
        return HttpResponseNotAllowed(['POST'])

signup과 signin의 전문입니다...ㅠㅠ

uyw4687 commented 4 years ago

signin하면 auth.login이 실행되면서 204를 return하나요? if user.is_active: 에서 걸리는 게 아닐까요?

GodDrinkTeJAVA commented 4 years ago

@uyw4687 204를 리턴합니다. 8ㅅ8...

ByungHeeCha commented 4 years ago

다른건 모르겠지만... 테스트 코드는 client.post('/api/signin/',...)client.login(...)으로 바꿔보는건 어떨까요?

ktaebum commented 4 years ago

아직 해결 안 된 이슈이죠?? 흠.. 정말 모르겠네요..

ByungHeeCha commented 4 years ago

혹시 Cookie가 잘못세팅되어 있는거 아닐까요? Cookie 잘못 세팅되면 AnonymousUser가 뜨는것 같은데요.

GodDrinkTeJAVA commented 4 years ago

image image

위와 같은 경우에 아래와 같이 입력하는 게 맞죠??ㅠㅠ... sessionid=gf6yp10hb7cuupk585jhu96iy0kltiwd; 입니다. 커서로 가려져서...

ktaebum commented 4 years ago

네 저 경우에는 저렇게 입력하는 게 맞습니다

GodDrinkTeJAVA commented 4 years ago

178 으로 미루어보아 ARC에서 자체적으로 sessionid(구체적으로는 resful test를 할 때 처음으로 받았던 sessionid)를 하나 더 보내고 있어서 로그인이 되지 않은 것으로 보입니다. 파이어폭스 부가기능 RESTED를 이용하여 확인한 결과 정상적으로 작동하는 것을 확인하였습니다.