【问题标题】:NTLM authentication javaNTLM 身份验证 java
【发布时间】:2014-06-05 16:59:15
【问题描述】:

我正在 Java EE 中编写 NTLM 身份验证。如果在 Internet Explorer 等浏览器中启用了“Windows 集成身份验证”,那么一切正常(浏览器将用户名发送到服务器)。但是如果像 Mozilla firefox 那样禁用“windows 集成身份验证”,浏览器会显示一个 at 身份验证表单,用户必须在其中输入他的登录名和密码。 我的问题是:在第二种情况下,当用户输入他的登录名和密码时,我可以从服务器端登录,但我无法获取密码。我必须得到一个密码,否则每个用户只需要知道另一个用户的用户名就可以在他的位置进行身份验证。

我的代码如下:

 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);

【问题讨论】:

  • NTLM 不会给你密码,它是一种质询响应机制。在您的 J2EE 容器中肯定存在一些 NTLM 身份验证器,不是吗?
  • 不,您的 J2EE 容器中没有 NTLM 身份验证器,有一些库。但我想从“浏览器的表单对话框”中获取“用户名+密码”??
  • 你不能; NTLM 根本不发送密码。

标签: java authentication single-sign-on ntlm


【解决方案1】:

您需要发送以下 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"

【讨论】:

    【解决方案2】:
    String auth = request.getHeader("Authorization");
    //No NTLM authentification
    if (auth == null) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "NTLM");
        return;
    }
      //when the integrated authentication is disabled
     //basic authentication
     if((auth !=null)&&(!auth.startsWith("NTLM")))
    {
            {
            StringTokenizer st = new StringTokenizer(auth);
            if(st.hasMoreTokens()){
    
                String basic = st.nextToken();
                if (basic.equalsIgnoreCase("Basic")) {
                try{
                  String credentials = new String(Base64.decode(st.nextToken()));  
                    int p = credentials.indexOf(":");
                    if (p != -1) {
                         username = credentials.substring(0, p).trim();
                         password = credentials.substring(p + 1).trim();
                    } 
                }catch(Exception e){
    
    
                }
            }
            } 
        }
    
        }
    
    //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;
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      您为什么要在专有的东西上浪费时间?使用Kerberos

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-13
        相关资源
        最近更新 更多