Einstellung Authentication Header im Servlet über Filter
Vorwort
Dies ist mein Erster Versuch einen Filter, sanft sein.
Projektbeschreibung
Ich versuche abzuschließen, der einen build für eine Einzelanmeldung für mehrere Anwendungen und ich scheine gegen eine Wand. Die webapp, ich bin versucht zu verbinden kommt die "Authentifizierung" - header, um zu bestimmen, Anmeldeinformationen des Benutzers innerhalb der Anwendung. Ich habe einen Filter gebaut, mit der Hoffnung, die Einstellung des headers, bevor es an die webapp.
Das Problem
Übergibt der code der eclipse-Validierung, kompiliert, geladen, Tomcat, und gelangt durch die webapp. Das einzige, was fehlt, ist der header Authentifizierung.
Was ich bin fehlt/falsch?
AuthenticationFilter Quelle
package xxx.xxx.xxx.xxx.filters;
import java.io.IOException;
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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import xxx.xxx.xxx.ConfigFile;
import xxx.xxx.xxx.Console;
import xxx.xxx.xxx.FalseException;
import xxx.xxx.activity.EncryptUtil;
public class AuthenticationFilter implements Filter {
public ConfigFile config;
public void init(FilterConfig arg0) throws ServletException {
config = new ConfigFile("C:/config.properties");
}
public void doFilter(ServletRequest sRequest, ServletResponse sResponse, FilterChain filterChain) throws IOException, ServletException {
Console.debug("AuthenticationFilter.doFilter() triggered.");
ServletRequestWrapper request = new ServletRequestWrapper((HttpServletRequest) sRequest);
HttpServletResponse response = (HttpServletResponse) sResponse;
HttpSession session = request.getSession();
Cookie cookie = null;
try {
if (request.getParameter("logout") != null) {
session.invalidate();
throw new FalseException("Logout recieved");
}
String auth = request.getHeader("Authorization");
if (auth == null) {
Console.debug("Authorization Header not found.");
//get cookie --COOKIE NAME--
Cookie[] cookies = request.getCookies();
if (cookies == null) {
throw new FalseException("Cookies not set.");
}
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equals(config.getProperty("authentication.cookie.name"))) {
cookie = cookies[i];
}
}
if (cookie == null) {
throw new FalseException("Cannot find Cookie (" + config.getProperty("authentication.cookie.name") + ") on Client");
}
Console.debug("Cookie (" + config.getProperty("authentication.cookie.name") + ") found on Client. value="+cookie.getValue());
String decToken = decryptToken(cookie.getValue());
Console.debug("Decrypted Token: "+decToken);
Console.debug("Setting Authorization Header...");
request.setAttribute("Authorization", decToken);
request.addHeader("Authorization", decryptToken(cookie.getValue()));
Console.debug("Authorization Header set.");
Console.debug("Validating Authorization Header value: "+request.getHeader("Authorization"));
}
}catch (FalseException e) {
Console.msg(e.getMessage() + ", giving the boot.");
response.sendRedirect(config.getProperty("application.login.url"));
} catch (Exception e) {
Console.error(e);
}
Console.debug("AuthenticationFilter.doFilter() finished.");
filterChain.doFilter(request, response);
}
public void destroy() {
}
private String decryptToken(String encToken) {
String token = null;
token = EncryptUtil.decryptFromString(encToken);
return token;
}
}
web.xml Quelle
<web-app>
<filter>
<filter-name>AuthenticationFilter</filter-name>
<display-name>AuthenticationFilter</display-name>
<description></description>
<filter-class>com.xxx.xxx.xxx.filters.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
ServletRequestWrapper Quelle
package com.xxx.xxx.xxx.filters;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public class ServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {
public ServletRequestWrapper(HttpServletRequest request) {
super(request);
headerMap = new HashMap();
}
private Map headerMap;
public void addHeader(String name, String value) {
headerMap.put(name, new String(value));
}
public Enumeration getHeaderNames() {
HttpServletRequest request = (HttpServletRequest) getRequest();
List list = new ArrayList();
for (Enumeration e = request.getHeaderNames(); e.hasMoreElements();) {
list.add(e.nextElement().toString());
}
for (Iterator i = headerMap.keySet().iterator(); i.hasNext();) {
list.add(i.next());
}
return Collections.enumeration(list);
}
public String getHeader(String name) {
Object value;
if ((value = headerMap.get("" + name)) != null)
return value.toString();
else
return ((HttpServletRequest) getRequest()).getHeader(name);
}
}
Debug-Log
LoginServlet.doGet() triggered.
[DEBUG] : Authenticate.isClientLoggedIn() triggered.
xxx url : https://xxx.xxx.xxx/xxx/home.action
[DEBUG] : Authenticate.isClientLoggedIn() status code: 401
Unauthorized User.
Client IS NOT logged in.
-- Fill out Login Form, submit --
LoginServlet.doPost() triggered.
[DEBUG] : Authenticate.isClientLoggedIn() triggered.
xxx url : https://xxx.xxx.xxx./xxx/home.action
[DEBUG] : Authenticate.isClientLoggedIn() status code: 401
Unauthorized User.
Client IS NOT logged in.
Client (--USERID--) attempting basic authentication with password(--PASSWORD--).
[DEBUG] : BasicAuthentication.touch(http://localhost:PORT/vu/loginCheck.html, --USERID--, --PASSWORD--) triggered.
[DEBUG] : BasicAuthentication.touch() response code: 200
Client (--USERID--) has been logged IN.
Client (--USERID--) basic authentication finished, Client is logged in.
Client (--USERID--) logged in successfully.
[DEBUG] : Cookie (xxx_token) Set: 1e426f19ebdfef05dec6544307addc75401ecdc908a3c7e6df5336c744--SECRET--
[DEBUG] : Redirecting client to https://xxx.xxx.xxx/xxx/home.action
-- Redirected to webapp, filter recieves --
[DEBUG] : AuthenticationFilter.doFilter() triggered.
[DEBUG] : Authorization Header not found. << Initical check to see if user is already logged in to site
[DEBUG] : Cookie (xxx_token) found on Client. value=1e426f19ebdfef05dec6544307addc75401ecdc908a3c7e6df5336c744--SECRET--
[DEBUG] : Decrypted Token: Basic --SECRET--
[DEBUG] : Setting Authorization Header...
[DEBUG] : Authorization Header set.
[DEBUG] : Validating Authorization Header value: Basic --SECRET-- << Value matches Decrypted Token
[DEBUG] : AuthenticationFilter.doFilter() finished.
-- Web Application errors out, unable to find Authorization header
Vielen Dank für Ihre Hilfe.
Weiß, werde ich im Hinterkopf behalten. Ich habe versucht, meinen Prozess und Fehlern zu trennen, ohne einen Haufen von hässlichen if-Anweisungen. Es spielt keine Entschuldigung für mein Verhalten ist, ist einfach erklärt.
Sie sagte, dass dies kompiliert, aber ich kann nicht finden, eine addHeader () - Methode auf ServletRequestWrapper.
Sorry benutzerdefinierte wrapper-Klasse, die ich leider nicht in der post. Ich werde es jetzt.
OK, wie genau haben Sie zu dem Schluss, dass der header fehlt? Hast du debug -
request.getHeader()
in der webapp von Interesse? Der Aufruf der webapp ist der Erhalt einer Instanz von ServletRequestWrapper
?InformationsquelleAutor PseudoNinja | 2011-02-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bin das hinzufügen einer neuen Antwort, da es ganz anders.
Ich habe einen test auf meinem system. Ich Kopier deinen code, warf den cookie-test, und schrieb ein einfaches Servlet-dump, die Dinge für mich.
Und es funktionierte gut, außer für eine Einschränkung.
Ich weiß nicht, wie Sie Ihre app mithilfe dieser. Aber Ihr
ServletRequestWrapper
implementiertgetHeaderNames
, undgetHeader
, aber es NICHT umsetzengetHeaders
. Ich lief in dieses problem, wie ichgetHeaders
um zu versuchen und werfen den Wunsch, und, natürlich, die Genehmigung fehlte.So, möchten Sie vielleicht Blick auf deinen code näher, um zu sehen, wenn es in der Tat nicht mit
getHeaders
. Wenn es ist, wird es "funktionieren", aber komplett überspringen der Arbeit, die Sie getan haben, und damit verpassen Sie Ihrem Authorization-header.Hier ist meine Umsetzung, und es funktionierte für mich.
InformationsquelleAutor Will Hartung
Erste, die grundlegendste Frage (Art "ist dieser eingesteckt?" - Frage) gehe ich davon aus, dass Ihre cookies sind alle verwurzelt in der gleichen Domäne sind, und dass Sie nicht versuchen, um cross-domain-Verhalten hier. Weil cookies nicht tun.
Jenseits der cookie-test, das sieht gut aus. Aber es sind alle Scharniere an den cookie-test.
Wenn Sie möchten, testen Sie den Authorization-header, dann können Sie einfach zu einem Kurzschluss der cookie-test (d.h. es immer geht), und füllen Sie den Authorization-header mit einigen gültigen Wert. Das wird in der kurzen Frist, testen Sie Ihre ganze Autorisierungs-Schema.
Sobald das erledigt/behoben werden, dann können Sie konzentrieren sich auf die cookie-Einstellung und Lieferung.
Ich auch davon ausgehen, dass Sie nicht mit Java-EE-Container-basierte Authentifizierung mit Tomcat zu tun dies für Sie prüfen. In diesem Fall wird ein filter einfach "zu spät". Die container haben bereits Entscheidungen, bevor Sie Ihre filter selbst aufgerufen wird.
Wenn Sie mit container-basierte Authentifizierung und Ihre apps sind auf dem gleichen container, ich könnte mir vorstellen, Tomcat (oder jemand) hat ein SSO-option auf der container-Ebene. Ich weiß, dass Glassfish wird dies für Sie aus der box. Es sollte unkompliziert sein, ändern die Tomcat-Artefakte (also nicht portable Java EE/Servlet-Mechanismen), um diesen umzusetzen, wenn das der Fall ist.
Normalerweise würde ich Zustimmen, mit Sie Jungs, aber die Projekt-Anforderungen besagen, dass der Login muss zur Unterstützung der vorhandenen Benutzer-management, das passiert einfach zu Basic-Authentifizierung. Die Anwendung selbst verwendet die Informationen in der Kopfzeile, um füllen Sie Informationen auf der Website.
Ich war nicht darauf hindeutet, Sie ändern zu Container-basierte Authentifizierung. Aber, klar zu sein, die Behälter TUN die Standardauthentifizierung unterstützt. Aber müssten Sie ändern, um Ihre Anwendung für die Verwendung des Servlet-security interface (isUserInRole, getPrincipal, etc.).
Und das ist der Grund für den filter, weil ich kann nicht (leicht) ändern Sie die app. Schließlich wird das Projekt verschieben zu Hash-Tabelle, aber in der Zwischenzeit, hier sind wir.
InformationsquelleAutor Will Hartung