2014-06-05 4 views
0

Java EE에서 NTLM 인증을 프로그래밍하고 있습니다. "Windows 통합 인증"이 Internet Explorer와 같이 브라우저에서 활성화되어 있으면 모든 것이 올바르게 작동합니다 (브라우저가 사용자 이름을 서버로 전송 함). 그러나 "Windows 통합 인증"이 Mozilla Firefox와 같이 비활성화 된 경우 브라우저는 사용자가 로그인 및 비밀번호를 입력해야하는 인증 양식을 표시합니다. 내 문제는 : 두 번째 경우 사용자가 로그인과 암호를 입력하면 서버 쪽에서 로그인 할 수 있지만 암호를 얻을 수 없습니다. 나는 암호를 알아야하는데, 그렇지 않으면 모든 사용자는 다른 사용자의 사용자 이름을 알고 자신의 위치에서 인증을 받아야합니다. 아래NTLM 인증 java

내 코드 :

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

NTLM 당신에게 암호를 제공하지 않을 , 그것은 도전 대응 메커니즘입니다. 분명히 J2EE 컨테이너에 NTLM 인증 프로그램이 존재합니까? 아닙니다. –

+0

아니요 J2EE 컨테이너에 NTLM 인증 프로그램이 없으므로 일부 librairies가 있습니다. 하지만 "BROWSER 'S FORAL DIALOG"에서 "username + password"를 받고 싶습니다. " – Shakveny

+0

수 없습니다. NTLM은 단순히 암호를 보내지 않습니다. –

답변

-1

이 왜 독점 물건 당신의 시간을 낭비하고? Kerberos을 사용하십시오.

0

당신은 클라이언트에서 암호를 얻기 위해 다음 HTTP 헤더를 보낼 필요가 :

WWW-Authenticate: Basic realm="insert realm" 

문제는 NTLM 또는 기본 인증을 요청할지 여부를 결정하는 방법이다. 한 가지 방법은 응답을 확인할 수없는 경우를 대비하여 NTLM을 먼저 묻는 것입니다. 그런 다음 기본을 묻습니다 (따라서 암호를 얻으십시오). 클라이언트가 어떤 브라우저를 사용하는지 또는 어떤 IP에서 액세스하는지 여부를 서버 측에서 감지하고이 데이터를 기반으로 NTLM 또는 Basic을 사용할 것인지 여부를 결정할 수 있습니다.

일부 브라우저도 동시에 NTLM 및 기본 헤더를 모두 받고 처리하고 결정할 수있는 한 자신의 능력에 따라 사용 :

WWW-Authenticate: NTLM 
WWW-Authenticate: Basic realm="insert realm" 
+0

감사합니다, 해결책은, – Shakveny

0
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; 
    } 

}