웹서비스에 한글 아이디를 허용하게 되면 난감해지는 HTTP적인 이유

그건 Basic Authentication 때문이다.

웹서비스에 한글 아이디를 허용하면 Basic Authentication을 적용하기 어려워진다.

뭐가 문제인가

HTTP의 Basic Authentication은 매우 단순한 인증 체계이다. 클라이언트가 사용자의 아이디와 비밀번호를 “아이디:비밀번호” 꼴로 만들어 base64 인코딩하여 전송하면, 서버가 확인 후 틀렸으면 401 Unauthorized를 돌려주고 맞았으면 요청을 적절히 처리한다.

보통 웹브라우저로 사이트에 들어가는데 팝업이 짠 뜨면서 로그인을 요구하면 대개 이 Basic Authentication이라고 보면 된다. 좀 더 복잡한 Digest Authentication이란 것도 있긴 한데 있긴 한데 별로 인기가 없다. 어차피 안전하지 않은 건 둘 다 마찬가지라 그럴바엔 그냥 쉬운 것을 선호하게 되는 모양이다.

근데 이 Basic Authentication 체계에서는 한글 아이디나 비밀번호를 사용할 수 없다.

Basic Authentication를 정의한 RFC 2617에 따르면, 아이디는 “:”를 제외한 0자 이상의 TEXT이고 비밀번호는 그냥 0자 이상의 TEXT다. 그럼 대체 TEXT는 뭘까?

The TEXT rule is only used for descriptive field contents and values
that are not intended to be interpreted by the message parser. Words
of *TEXT MAY contain characters from character sets other than ISO-
8859-1 [22] only when encoded according to the rules of RFC 2047

HTTP/1.1을 정의한 RFC 2616에 따르면 TEXT는 ISO-8859-1로 정의된 문자집합에 속한 문자만을 사용해야하며, 그렇지 않은 경우에는 RFC 2047의 인코딩 규칙을 따라야 한다.

RFC 2047의 인코딩 규칙이란 대략 요렇게 생긴 것들이다. 아마 웹브라우저로 파일 다운로드 받다 뭔가 잘못되었을 때 종종 봤을 것이다. (( 웹브라우저마다 파일 이름을 코딩하는 방식이 제각각이라 그런 문제가 종종 생긴다. 자세한 것은 여기를 보라. ))

=?iso-8859-1?q?this is some text?=

자 그럼, 저 요상하게 생긴 방식으로 인코딩을 하면 아무 문제없이 한글 아이디를 써도 Basic Authentication이 가능할 것 같은 기분이 든다.

근데 아니다.

예전에 Stackoverflow에 Basic Authentication의 아이디와 패스워드는 대체 뭘로 디코딩해야 하는가에 대한 질문이 올라온 일이 있었는데, 답변은 “ISO-8859-1” 흑은 “undefined” 니까 네가 하고 싶은대로 해라.였다.

아니 스펙에 분명 RFC 2047도 된다고 하는데 이 답변자는 뭐하시는 분이길래 하고 봤더니만 Julian Reschke였다. HTTP/1.1을 고쳐쓰는 httpbis의 저자 중 한명이다. 그에 따르면 httpbis에선 RFC 2047을 적용 가능함에 대한 언급이 빠진다고 한다.

실제 구현들은 어떠한가

“ISO-8859-1” 혹은 “undefined” 라니 참으로 애매해다. 이런 모호한 상황을 유명 웹서버들은 어떻게 해결했을까. 구현을 들여다보자.

다음은 Apache Tomcat의 구현이다.

username = new String(buf, 0, colon);
password = new String(buf, colon + 1,
        authorizationCC.getEnd() - colon - 1);

인코딩을 정해주지 않았다. 이런 경우 시스템 설정을 따라갈 것이다.

jetty6은 ISO-8859-1로 디코딩한다.

credentials = B64Code.decode(credentials,StringUtil.__ISO_8859_1);

cpython은 ascii로 디코딩한다. ISO-8859-1 보다 작은 문자집합이다.

authorization = base64.decodebytes(authorization).
                decode('ascii')

한번 자신이 애용하는 웹서버의 소스코드를 들여다보라. 아마 UTF-8로 디코딩하는 경우는 거의 없을 것이다.

결론

웹애플리케이션을 만들면서 아이디를 한글도 가능하게 하려고 생각하고 있다면 다시 한번 생각해보길 바란다. Basic Authentication을 붙일 일이 생기면 골치아파질 수 있다.

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중