繁体   English   中英

NTLM身份验证Java

[英]NTLM authentication java

我正在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);

您需要发送以下HTTP标头,以从客户端获取密码:

WWW-Authenticate: Basic realm="insert realm"

问题是如何决定是否请求NTLM或基本身份验证。 一种方法是,如果无法验证响应,则首先要求NTLM,然后要求“基本”(并因此获得密码)。 您还可以在服务器端检测您的客户端使用哪个浏览器或他从哪个IP访问,并根据此数据决定使用NTLM还是Basic。

某些浏览器还可以同时获取NTLM和Basic标头,并根据其功能决定使用哪个标头:

WWW-Authenticate: NTLM
WWW-Authenticate: Basic realm="insert realm"
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;
    }

}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM