Имя пользователя j_security_check в кодировке UTF-8 неправильно декодируется как Latin-1 в сфере Tomcat

Я исследую проблему, из-за которой имя пользователя с символом Latin-1 вводится в форму входа. Имя пользователя содержит символ á. Я исследую серверную часть, где у меня есть:

открытый класс MyRealm расширяет RealmBase, реализует Realm {public Principal authentication(строковое имя пользователя, строковый пароль) {... фактическая аутентификация реализована здесь} }

Если я распечатаю байты: username.getBytes(), я увижу, что символ á имеет: C3 83 C2 A1 Обычно символ á в кодировке UTF8 должен иметь: C3 A1. Если я снова закодирую это в UTF8, я получу: C3 83 C2 A1 то, что распечатывает мое программное обеспечение.

Я проверил в сети захват, что имя пользователя отправляется правильно с C3 A1. Исходный код формы страницы входа:

        <form name="loginForm" action="j_security_check" method="post" enctype="application/x-www-form-urlencoded">
        <table>
            <tr>
                <td colspan="2" align="right">Secure connection:
                    <input type="checkbox" name="checkbox" class="style5" onclick="javascript:httpHttps();"></td>
            </tr>
            <tr>
                <td class="style5">Login:</td>
                <td><input type="text" name="j_username" autocomplete="off" style="width:150px" /></td>
            </tr>

Так что я думаю, что на стороне клиента нет ничего плохого (2-кратное преобразование UTF8). Если я два раза декодирую обратно из UTF8 в функции authentication(), имя пользователя, тогда аутентификация работает нормально, но я боюсь применять это решение к моей проблеме.

Где я должен искать эту кодировку имени пользователя в функции аутентификации Realm (строковое имя пользователя, строковый пароль)? Серверная часть работает на Linux (RedHat) с httpd-2.2.15 и tomcat6-6.0.24.


person wildfrontier    schedule 15.12.2014    source источник


Ответы (1)


В вашем примере ваша форма отправляет символ UTF-8 для «á» в Tomcat, используя кодировку% (поэтому по проводу это% C3% A1). Однако Tomcat будет интерпретировать его как Latin1, который является кодировкой по умолчанию для POST.

Таким образом, Tomcat будет хранить C3A1 как «Ã¡» внутри, поскольку C3 — это «Ã», а A1 — «¡» в кодировке Latin1.

Когда вы запросите username.getBytes(), он создаст массив байтов в кодировке UTF-8, поэтому он ищет два символа «Ã¡» в наборе символов UTF-8, который является C383 C2A1.

Часто задаваемые вопросы, в которых подробно описывается это и предлагаемое решение: http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q3

Измените Valve FormAuthenticator в server.xml, чтобы указать characterEncoding="UTF-8"

    <Context path="/YourSercureApp">
            <Valve
            className="org.apache.catalina.authenticator.FormAuthenticator"
            disableProxyCaching="false"
            characterEncoding="UTF-8" />
    </Context>
person tamasp    schedule 19.01.2015
comment
Добро пожаловать в Stack Exchange и спасибо за помощь. В идеале решения в ответах должны быть самодостаточными, с кодом на этом сайте - не в ссылке. Таким образом, нам не нужно беспокоиться о неработающих ссылках, если сайт будет реструктурирован, и кто-то с той же проблемой в следующем году посетит stackoverflow. - person David Manheim; 19.01.2015