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 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() 를 둘 다 한다. 한쪽만 해도 되는지는 모른다. 상태를 가진 물건은 만들 때만이 아니라 지울 때도 생각해야 한다는 걸 여기서 처음 알았다.

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

정리


Share this post on:

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