L'Authentification NTLM dans une Application Web (java)
Je suis à l'aide de filtre suivant pour activer l'Authentification NTLM, dans mon application web.
- Je obtenir les fenêtres de navigateur invite d'authentification.
Il fonctionne très bien. Sauf pour le fait qu' - je suis incapable de dire si l'Authentification a Réussi ou Échoué !!! *Il n'y a pas d'erreurs dans les deux cas.* Dans tous les cas, le nom d'utilisateur(correcte ou non), poste de travail, etc. est imprimé.
package com.test;
import java.io.IOException;
import java.io.PrintStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jcifs.ntlmssp.Type3Message;
import com.sun.xml.internal.ws.util.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class NTLMUserFilter implements Filter {
private FilterConfig filterConfig = null;
private String userDomain = null;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String username = null;
//first, get the user agent
String useragent = request.getHeader("user-agent");
//if you're using IE, you can continue
if ((useragent.indexOf("MSIE") > -1)){
//Always do the ntlm check (for IE POST back)
try{
String auth = request.getHeader("Authorization");
if (auth == null)
{
response.setHeader("WWW-Authenticate", "NTLM");
response.setStatus(response.SC_UNAUTHORIZED);
response.setContentLength(0) ;
response.flushBuffer();
return;
}
if (auth.startsWith("NTLM "))
{
byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
int off = 0, length, offset;
if (msg[8] == 1)
{
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};
response.setHeader("WWW-Authenticate", "NTLM " + new sun.misc.BASE64Encoder().encodeBuffer(msg1));
response.setStatus(response.SC_UNAUTHORIZED);
response.setContentLength(0) ;
response.flushBuffer();
return;
}
else if (msg[8] == 3)
{
//Did Authentication Succeed? All this is always printed.
Type3Message type3 = new Type3Message(msg);
System.out.println("osUser: " + type3.getUser());
System.out.println("osRemoteHost: + " + type3.getWorkstation());
System.out.println("osDomain: " + type3.getDomain());
}
}
}catch(Exception e){
System.out.println(e) ;
}
//System.out.println("Suc);
}
try {
chain.doFilter(req, res);
} catch (IOException e) {
System.out.println(e);
} catch (ServletException e) {
System.out.println(e);
}
}
public void destroy()
{
this.filterConfig = null;
}
}
L'web.xml est simple:
<filter>
<filter-name>ntlmFilter</filter-name>
<filter-class>
com.test.NTLMUserFilter
</filter-class>
</filter>
<!-- Filter mapping configuration -->
<filter-mapping>
<filter-name>ntlmFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- Avez-vous essayé de capturer les messages provenant à la fois un succès et un échec d'ouverture de session, et de les comparer côte à côte?
Vous devez vous connecter pour publier un commentaire.
Vous recevez le message de Type 3, mais vous ne faites pas quelque chose avec elle, à l'exception d'imprimer les détails. Vous devez valider le client de la réponse à ce point, et d'envoyer un 200 (si autorisé) ou 401 (si non).
Cependant le Type 1 message délivré est composé de statique octets et - bien qu'il va induire un client de renvoyer une réponse est la plupart du temps vide de sens. Il n'est pas impossible à mettre en œuvre complète de l'authentification NTLM pile vous-même, mais le code que vous avez tout simplement pas de travail.
Vous pourriez enquêter sur un NTLM Solution pour Java, ou (si vous êtes sous Windows), vous pouvez appeler l'authentification nécessaire des fonctions comme
AcceptSecurityContext
avec JNI.Comme Edward said, juste de l'extraction d'un nom à partir d'un type 3 (réponse) NTLM message ne dit rien sur le fait que le client qui est à l'origine il était en droit de le faire.
NTLM n'est pas comme Kerberos, où il y a un jeton signé qu'un service peut valider sur son propre, vous devez établir la connexion à un contrôleur de domaine à chaque fois pour lui demander si le jeton est légitime. Mise en œuvre d'un MSRPC la connexion pour vérifier une NTLM est vraiment un travail difficile.
Dans l'ancien temps, vous pouvez le faire dans JCIFS à l'aide d'un
jcifs.smb.SmbSession
, etjcifs.http.NtlmHttpFilter
le ferait pour vous. Toutefois, cela ne fonctionne que pour NTLMv1, qui est l'ancien, de l'insécurité, et de plus en plus rare d'être utilisé pour quoi que ce soit. (Je crois "ntlm-java" lié ci-dessus est également NTLMv1 seule.)Essayer le ntlmv2auth projet.
NTLM-over-HTTP est assez d'une douleur dans le cul qu'il est généralement préférable d'utiliser toute autre méthode d'authentification disponibles pour vous.