Java-аутентификация NTLM

Я программирую аутентификацию NTLM в Java EE. Если в браузере включена «интегрированная аутентификация Windows», например Internet Explorer, все работает хорошо (браузер отправляет имя пользователя на сервер). Но если «встроенная аутентификация Windows» отключена, как в Mozilla firefox, браузер отображает форму аутентификации, где пользователь должен ввести свой логин и пароль. Моя проблема: во втором случае, когда пользователь вводит свой логин и пароль, я могу получить логин со стороны сервера, но не могу получить пароль. Я должен получить пароль, иначе каждому пользователю нужно просто знать имя пользователя другого пользователя, чтобы пройти аутентификацию вместо него.

Мой код ниже:

 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    /**
     * NTLM
     */
    String auth = request.getHeader("Authorization");
    //No NTLM authentification
    if (auth == null) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "NTLM");
        return;
    }
    //check what client sent
    if (auth.startsWith("NTLM")) {
        byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
        int off = 0, length, offset;

        if (msg[8] == 1) {
            off = 18;
            byte z = 0;
            byte[] msg1 = {(byte) 'N', (byte) 'T', (byte) 'L', (byte) 'M', (byte) 'S',
                (byte) 'S', (byte) 'P', z,
                (byte) 2, z, z, z, z, z, z, z,
                (byte) 40, z, z, z, (byte) 1, (byte) 130, z, z,
                z, (byte) 2, (byte) 2, (byte) 2, z, z, z, z,
                z, z, z, z, z, z, z, z};

            // send ntlm type2 msg
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setHeader("WWW-Authenticate", "NTLM " + new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());
            return;
        } //receive ntlm type 3 msg
        else if (msg[8] == 3) {
            off = 30;

            //username
            length = msg[off + 9] * 256 + msg[off + 8];
            offset = msg[off + 11] * 256 + msg[off + 10];
            username = new String(msg, offset, length);

            //remoteHost
            length = msg[off + 17] * 256 + msg[off + 16];
            offset = msg[off + 19] * 256 + msg[off + 18];
            remoteHost = new String(msg, offset, length);

            //domain
            length = msg[off + 1] * 256 + msg[off];
            offset = msg[off + 3] * 256 + msg[off + 2];
            domain = new String(msg, offset, length);
        } else {
            return;
        }

    }
    /**
     * END NTLM
     */

    request.setAttribute("username", username);
    request.setAttribute("remoteHost", remoteHost);
    request.setAttribute("domain", domain);
    request.setAttribute("ipAdress", request.getRemoteAddr());
    request.setAttribute("remotePort", request.getRemotePort());
    request.setAttribute("protocol", request.getProtocol());
    this.getServletContext().getRequestDispatcher("/WEB-INF/index.jsp").forward(request, response);

person Shakveny    schedule 05.06.2014    source источник
comment
NTLM не даст вам пароль, это механизм ответа на запрос. Наверняка в вашем J2EE-контейнере есть какой-нибудь аутентификатор NTLM, не так ли?   -  person Edward Thomson    schedule 05.06.2014
comment
нет, в вашем контейнере J2EE нет аутентификатора NTLM, есть несколько библиотек. Но я хочу получить имя пользователя + пароль из ДИАЛОГА ФОРМЫ БРАУЗЕРА ??   -  person Shakveny    schedule 06.06.2014
comment
Тебе нельзя; NTLM просто не отправляет пароль.   -  person Edward Thomson    schedule 06.06.2014


Ответы (2)


Зачем вы тратите свое время на проприетарные вещи? Используйте Kerberos.

person Michael-O    schedule 05.06.2014

Вам необходимо отправить следующий HTTP-заголовок, чтобы получить пароль от клиента:

WWW-Authenticate: Basic realm="insert realm"

Проблема заключается в том, как решить, запрашивать ли аутентификацию NTLM или Basic. Один из подходов состоит в том, чтобы сначала запросить NTLM, если ответ не может быть проверен, а затем запросить Basic (и, следовательно, получить пароль). Вы также можете определить на стороне сервера, какой браузер использует ваш клиент или с какого IP-адреса он получает доступ, и решить, использовать ли NTLM или Basic на основе этих данных.

Некоторые браузеры также могут одновременно обрабатывать заголовки NTLM и Basic и решать, какой из них использовать, исходя из своих возможностей:

WWW-Authenticate: NTLM
WWW-Authenticate: Basic realm="insert realm"
person Vladimír Schäfer    schedule 06.06.2014