Skip to content
isdnetworks
Go back

로그인은 되는데 다음 요청에서 풀렸다

(수정됨)

앱에서 로그인 API 를 부르면 성공이 온다. 그다음 API 는 로그인이 필요하다고 했다. 방금 로그인했는데 왜.

Table of contents

Open Table of contents

증상 — 앱에서만 풀리는 로그인

순서대로 의심하고 하나씩 지웠다.

Servlet 로그를 보니 HttpSession 이 매번 새로 생기고 있었다. JSESSIONID 가 계속 달랐다.

서버가 아니라 앱 쪽이었다. 브라우저로 되고 앱으로 안 되면 브라우저가 하는 일 중에 내가 안 하는 것이 있다는 뜻이다.

브라우저가 대신 해 주던 일이 있었다

개발자 도구로 로그인 요청과 그다음 요청을 나란히 열어 봤다. 헤더에 내가 안 보내는 것이 하나 있었다.

1. 로그인 요청
2. 서버 → 응답 헤더에 Set-Cookie: JSESSIONID=abc123
3. 다음 요청 → 헤더에 Cookie: JSESSIONID=abc123 을 실어 보내야 함
4. 서버는 그 값으로 "아까 그 사람"인 걸 안다

브라우저는 2번에서 받은 값을 저장했다가 3번에서 자동으로 붙인다. Android 에는 그걸 해 주는 것이 없었다. 받은 JSESSIONID 를 아무도 안 들고 있었다.

부를 때마다 새로 만들고 있었다

쿠키를 저장하는 코드도 없지만 지우는 코드도 없었다. HttpClient 공식 문서의 쿠키 항목을 보니 쿠키는 클라이언트 인스턴스가 들고 있었다. 그럼 어디로 사라진 걸까. 로그인 부분과 조회 부분을 나란히 놓고 보다가 알았다.

// 로그인
HttpClient client = new DefaultHttpClient();
client.execute(loginPost);

// 내 정보 조회 — 다른 메서드
HttpClient client = new DefaultHttpClient();   // ← 여기
client.execute(infoGet);

DefaultHttpClient 는 안에 BasicCookieStore 를 들고 있다. 그런데 메서드마다 new DefaultHttpClient() 를 하고 있었다. 객체가 새로 생기면 CookieStore 도 빈다.

고치는 방법은 간단했다. 하나만 만들어 계속 쓰는 것이다.

public class ApiClient {
    private static HttpClient client;

    private static HttpClient get() {
        if (client == null) {
            client = new DefaultHttpClient();
        }
        return client;
    }
}

같은 객체를 계속 쓰니 쿠키가 다음 요청에 자동으로 붙었다. 지금 쓰면 당연한 이야기인데 그때는 객체가 상태를 들고 있다는 감각이 없었다.

로그아웃에서 또 막혔다

로그아웃을 해도 로그인 상태가 유지됐다. 당연했다. 로그아웃은 서버 세션을 끊는 것인데 앱이 들고 있는 쿠키는 그대로였다.

public static void clearSession() {
    ((AbstractHttpClient) get()).getCookieStore().clear();
}

지금은 로그아웃 API 와 clear() 를 둘 다 한다. 한쪽만 해도 되는지는 모른다. 상태를 가진 물건은 만들 때만이 아니라 지울 때도 생각해야 한다는 걸 여기서 처음 알았다.

앱을 껐다 켜면 메모리가 사라지니 쿠키도 사라진다. SharedPreferences 에 JSESSIONID 를 넣는 예제를 봤는데 그대로 두면 다른 앱이 볼 수 있다고 한다. 암호화해야 하는지는 아직 모른다.

정리


Share this post on:

Previous Post
로그를 남기게 해 뒀는데 안 남고 있었다
Next Post
버전 관리를 처음 쓰면서