Impostazione dell’Intestazione di Autenticazione in Servlet tramite Filtro

Prefazione

Questo è il mio primo tentativo di un Filtro, di essere gentile.

Descrizione Del Progetto

Sto cercando di portare a termine una build per un SSO per diverse applicazioni e mi sembra di essere di colpire un muro. La webapp sto tentando di collegare a usa il “Autenticazione” intestazione per determinare le credenziali dell’utente all’interno dell’applicazione. Io ho costruito un Filtro con la speranza di impostazione dell’intestazione prima di passare alla webapp.

Il Problema

Il codice passa eclipse convalida, compila carichi di Tomcat, e che passa attraverso la webapp. L’unica cosa che manca è l’intestazione di Autenticazione.

Quello che mi manca/facendo di sbagliato?

AuthenticationFilter fonte

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 fonte

<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 Fonte

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

}

Registro Di Debug

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 

Grazie per il vostro aiuto.

  • Solo un consiglio: si prega di non gettare Throwable, che è riservato per una grande rabbia di errori di solito preso solo dalla JVM, come ultima risorsa, e mai e poi mai prendere throwable o eccezioni in un filtro senza generazione ripetuta di loro.
  • Bianco, terrò a mente. Stavo cercando di tenere il mio processo e di errori separati senza un mucchio di brutto, se le istruzioni. Non si scusa per il mio comportamento, appena lo spiega.
  • Hai detto che questo viene compilato, ma non riesco a trovare una addHeader() metodo ServletRequestWrapper.
  • Mi dispiace personalizzato classe wrapper non ho incluso in post. Vorrei aggiungere ora.
  • La tua frase “La webapp sto tentando di collegare” è ambiguo. Elaborare in dettaglio. Per esempio, l’ho interpretato come l’utilizzo di URL#openConnection(), ma che sarebbe, ovviamente, non lavorare insieme con il vostro filtro (e che potrebbe essere la causa principale del tuo problema).
  • Ho un’applicazione web esistente in esecuzione su Tomcat 5.5. Nella versione corrente utilizza l’autenticazione di base per convalidare le credenziali dell’utente (e quindi l’intestazione di Autorizzazione). Questa applicazione analizza l’intestazione di Autorizzazione al fine di determinare la registrazione dell’utente (non mi chiedete, non lo scrivo).
  • OK, esattamente come hai fatto a concludere che l’intestazione mancante? Hai debug request.getHeader() nella webapp di interesse? È richiesta la webapp è la ricezione di un’istanza di ServletRequestWrapper?
  • L’intestazione mancante in Fiddler, Firebug(net), e la webapp di errori, perché non è possibile trovare le credenziali dell’utente. Sì, la richiesta è di ricevere è un’istanza della ServletRequestWrapper.
  • Veramente l’intestazione è presente, perché l’intestazione non è impostata dal cliente, ma da solo nel server. Aggiungere un punto di interruzione getHeader() di il wrapper e di debug.
  • Il suo passo correttamente, tuttavia, quando si verifica il cookie mi butta fuori perché il cookie non esiste in applicazione perché non è stato fatto riferimento da SSO. C’è un modo per impostare manualmente un cookie all’interno di eclipse eseguire il debug?
  • Non si può semplicemente inviare una richiesta con il cookie? Di dove sei di sperimentazione di questo allora? O il vostro locale/ambiente di test non corrispondere all’ambiente di produzione? Comunque, è possibile modificare le intestazioni di richiesta con Firefox tamperdata plugin.
  • La tua domanda, si può, si prega di indicare chiaramente il risultato atteso, invece, il risultato effettivo che si sta ottenendo? Effettivo println o registro istruzioni in codice sarebbe utile, con una spiegazione di come non corrisponda a quanto previsto.
  • Barnum: i File di Log sono stati aggiunti. L’Intestazione di Autorizzazione e cookie entrambi sembrano funzionare correttamente nel filtro, ma l’intestazione di Autorizzazione viene impostata non sembrano bastone attraverso la servlet.

InformationsquelleAutor PseudoNinja | 2011-02-04



2 Replies
  1. 9

    Io sono l’aggiunta di una nuova risposta, dal momento che è completamente diverso.

    Ho fatto un test sul mio sistema. Ho copiato il tuo codice, oggetto di dumping il cookie di prova, e ha scritto una semplice Servlet per eseguire il dump le cose per me.

    E ha funzionato bene, salvo che per un avvertimento.

    Non so come la tua applicazione è l’utilizzo di questo. Ma il tuo ServletRequestWrapper implementa getHeaderNames, e getHeader, ma NON implementa getHeaders. Mi sono imbattuto in questo problema ho usato getHeaders per cercare e scaricare la richiesta, e, naturalmente, l’Autorizzazione è mancante.

    Così, si potrebbe voler cercare il codice più vicino per vedere se è davvero il non utilizzo getHeaders. Se lo è, sarà “funzionare bene”, ma saltare completamente il lavoro che hai fatto, e, quindi, perdere l’intestazione di Autorizzazione.

    Ecco la mia implementazione, e ha funzionato per me.

        @Override
        public Enumeration getHeaders(String name) {
            Enumeration e = super.getHeaders(name);
            if (e != null && e.hasMoreElements()) {
                return e;
            } else {
                List l = new ArrayList();
                if (headerMap.get(name) != null) {
                    l.add(headerMap.get(name));
                }
                return Collections.enumeration(l);
            }
        }
    • funziona a meraviglia. Grazie ragazzi.
  2. 1

    Prima, la domanda fondamentale (una sorta di “questo è collegato” domanda), presumo che i tuoi biscotti sono tutti radicati nello stesso dominio, e che non stai cercando di ottenere il cross domain comportamento qui. Poiché i cookie non farlo.

    Oltre i cookie di prova, questo sembra bene. Ma tutto fa perno sul cookie test.

    Se si desidera verificare l’intestazione di Autorizzazione, allora si può semplicemente corto circuito il cookie di prova (cioè si passa sempre) e compilare l’intestazione di Autorizzazione con qualche valore valido. Questo sarà, a breve termine, prova tutta la vostra schema di Autorizzazione.

    Una volta fatto e/o fisse, quindi è possibile concentrarsi su l’impostazione dei cookie e di consegna.

    Ho anche supporre che non si utilizza Java EE Contenitore di autenticazione di base, con il gatto che fa questo controllo per voi. In questo caso, un filtro è semplicemente “troppo tardi”. Il contenitore avrà già fatto le decisioni di prima il filtro diventa anche chiamato.

    Se si utilizza il contenitore di autenticazione di base, e le app sono sullo stesso recipiente, immagino Tomcat (o qualcuno) è un’opzione SSO a livello contenitore. So che Glassfish farà questo per voi, fuori dalla scatola. Dovrebbe essere semplice per modificare Tomcat artefatti (cioè non portatile Java EE/Servlet meccanismi) per implementare questo, se è il caso.

    • Buona risposta. Vorrei anche sottolineare che la sicurezza è saggio consiglia di utilizzare l’applicazione server previste strutture per l’autenticazione e SSO. Probabilmente sono meglio è stato testato e più ampiamente analizzata. Sono particolarmente preoccupato per il EncryptionUtils menzionato.
    • Normalmente sarei d’accordo con voi ragazzi, ma le esigenze del progetto di stato che il Login è necessario il supporto utente esistente di gestione che accade solo per essere l’Autenticazione di Base. L’Applicazione utilizza le informazioni nell’intestazione di compilare le informazioni sul sito.
    • Non stavo suggerendo di cambiare Contenitore di autenticazione di base. Ma, per essere chiari, i contenitori NON supporta l’autenticazione di Base. Ma sarebbe necessario modificare l’applicazione per utilizzare il Servlet di protezione di interfaccia (isUserInRole, getPrincipal, etc.).
    • E che è il motivo per il filtro, io non (facilmente) modificare l’app. Alla fine il progetto si sposterà tabella di Hash, ma nel frattempo siamo qui.

Lascia un commento