[jboss-cvs] jboss-seam/src/main/org/jboss/seam/web ...

Shane Bryzak sbryzak at redhat.com
Tue May 22 23:44:25 EDT 2007


  User: sbryzak2
  Date: 07/05/22 23:44:25

  Modified:    src/main/org/jboss/seam/web  HttpAuthFilter.java
  Log:
  JBSEAM-743 still todo: testing, documentation, config
  
  Revision  Changes    Path
  1.2       +113 -5    jboss-seam/src/main/org/jboss/seam/web/HttpAuthFilter.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: HttpAuthFilter.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/web/HttpAuthFilter.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- HttpAuthFilter.java	21 May 2007 03:47:38 -0000	1.1
  +++ HttpAuthFilter.java	23 May 2007 03:44:25 -0000	1.2
  @@ -5,6 +5,8 @@
   import static org.jboss.seam.annotations.Install.BUILT_IN;
   
   import java.io.IOException;
  +import java.util.HashMap;
  +import java.util.Map;
   
   import javax.servlet.FilterChain;
   import javax.servlet.ServletException;
  @@ -16,16 +18,27 @@
   import org.jboss.seam.annotations.Filter;
   import org.jboss.seam.annotations.Install;
   import org.jboss.seam.annotations.Intercept;
  +import org.jboss.seam.annotations.Logger;
   import org.jboss.seam.annotations.Name;
   import org.jboss.seam.annotations.Scope;
   import org.jboss.seam.annotations.Startup;
   import org.jboss.seam.contexts.Context;
   import org.jboss.seam.contexts.WebSessionContext;
  +import org.jboss.seam.log.Log;
   import org.jboss.seam.security.Identity;
   import org.jboss.seam.security.NotLoggedInException;
  +import org.jboss.seam.security.digest.DigestRequest;
  +import org.jboss.seam.security.digest.DigestUtils;
  +import org.jboss.seam.security.digest.DigestValidationException;
   import org.jboss.seam.servlet.ServletSessionImpl;
   import org.jboss.seam.util.Base64;
   
  +/**
  + * Seam Servlet Filter supporting HTTP Basic and Digest authentication. Some code
  + * adapted from Acegi.
  + *  
  + * @author Shane Bryzak
  + */
   @Startup
   @Scope(APPLICATION)
   @Name("org.jboss.seam.web.httpAuthFilter")
  @@ -36,10 +49,15 @@
   {
      private static final String DEFAULT_REALM = "seamApp";
      
  +   @Logger Log log;
  +   
      public enum AuthType {basic, digest}
      
      private String realmName = DEFAULT_REALM;
      
  +   private String key;
  +   private int nonceValiditySeconds = 300;
  +   
      private AuthType authType = AuthType.basic;
      
      public void setRealmName(String realmName)
  @@ -62,6 +80,26 @@
         return authType;
      }
      
  +   public String getKey()
  +   {
  +      return key;
  +   }
  +   
  +   public void setKey(String key)
  +   {
  +      this.key = key;
  +   }
  +   
  +   public int getNonceValiditySeconds()
  +   {
  +      return nonceValiditySeconds;
  +   }
  +   
  +   public void setNonceValiditySeconds(int value)
  +   {
  +      this.nonceValiditySeconds = value;
  +   }
  +   
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
         throws IOException, ServletException
      {
  @@ -108,7 +146,6 @@
            }
   
            // Only reauthenticate if username doesn't match Identity.username and user isn't authenticated
  -
            if (!username.equals(identity.getUsername()) || !identity.isLoggedIn()) 
            {
               identity.setUsername(username);
  @@ -134,10 +171,81 @@
               HttpServletResponse response, FilterChain chain)
         throws IOException, ServletException
      {
  +      Context ctx = new WebSessionContext(new ServletSessionImpl(request.getSession()));
  +      Identity identity = (Identity) ctx.get(Identity.class);
  +      
  +      boolean failed = false;    
  +      boolean nonceExpired = false;
  +      
         String header = request.getHeader("Authorization");
  -      if (!header.startsWith("Digest "))
  +      if (header != null && header.startsWith("Digest "))
         {
  -         throw new IllegalArgumentException("Request contains invalid authorization type");
  +         String section212response = header.substring(7);
  +
  +         String[] headerEntries = section212response.split(",");
  +         Map<String,String> headerMap = new HashMap<String,String>();
  +         for (String entry : headerEntries)
  +         {
  +            String[] vals = entry.split("=");
  +            headerMap.put(vals[0].trim(), vals[1].replace("\"", "").trim());
  +         }
  +         
  +         identity.setUsername(headerMap.get("username"));
  +
  +         DigestRequest digestRequest = new DigestRequest();
  +         digestRequest.setSystemRealm(realmName);
  +         digestRequest.setRealm(headerMap.get("realm"));         
  +         digestRequest.setKey(key);
  +         digestRequest.setNonce(headerMap.get("nonce"));
  +         digestRequest.setUri(headerMap.get("uri"));
  +         digestRequest.setClientDigest(headerMap.get("response"));
  +         digestRequest.setQop(headerMap.get("qop"));
  +         digestRequest.setNonceCount(headerMap.get("nc"));
  +         digestRequest.setClientNonce(headerMap.get("cnonce"));
  +                  
  +         try
  +         {
  +            digestRequest.validate();
  +            ctx.set(DigestRequest.DIGEST_REQUEST, digestRequest);
  +         }
  +         catch (DigestValidationException ex)
  +         {
  +            log.error(String.format("Digest validation failed, header [%s]: %s",
  +                     section212response, ex.getMessage()));
  +            failed = true;
  +            
  +            if (ex.isNonceExpired()) nonceExpired = true;
  +         }            
  +      }
  +      
  +      if (!failed)
  +      {
  +         try
  +         {
  +            chain.doFilter(request, response);
  +            return;
  +         }
  +         catch (NotLoggedInException ex) {}
  +      }
  +      
  +      if (failed || !identity.isLoggedIn())
  +      {
  +         long expiryTime = System.currentTimeMillis() + (nonceValiditySeconds * 1000);
  +         
  +         String signatureValue = DigestUtils.md5Hex(expiryTime + ":" + key);
  +         String nonceValue = expiryTime + ":" + signatureValue;
  +         String nonceValueBase64 = Base64.encodeBytes(nonceValue.getBytes());
  +
  +         // qop is quality of protection, as defined by RFC 2617.
  +         // we do not use opaque due to IE violation of RFC 2617 in not
  +         // representing opaque on subsequent requests in same session.
  +         String authenticateHeader = "Digest realm=\"" + realmName + "\", " + "qop=\"auth\", nonce=\""
  +             + nonceValueBase64 + "\"";
  +
  +         if (nonceExpired) authenticateHeader = authenticateHeader + ", stale=\"true\"";
  +
  +         response.addHeader("WWW-Authenticate", authenticateHeader);
  +         response.sendError(HttpServletResponse.SC_UNAUTHORIZED);      
         }      
      }
   }
  
  
  



More information about the jboss-cvs-commits mailing list