[jboss-cvs] jboss-seam/src/main/org/jboss/seam/web ...
Shane Bryzak
sbryzak at redhat.com
Tue May 29 20:52:59 EDT 2007
User: sbryzak2
Date: 07/05/29 20:52:59
Added: src/main/org/jboss/seam/web AuthenticationFilter.java
Removed: src/main/org/jboss/seam/web HttpAuthFilter.java
Log:
rename authentication filter, fix compiler error
Revision Changes Path
1.1 date: 2007/05/30 00:52:59; author: sbryzak2; state: Exp;jboss-seam/src/main/org/jboss/seam/web/AuthenticationFilter.java
Index: AuthenticationFilter.java
===================================================================
package org.jboss.seam.web;
import static org.jboss.seam.InterceptionType.NEVER;
import static org.jboss.seam.ScopeType.APPLICATION;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.faces.event.PhaseId;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
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.Lifecycle;
import org.jboss.seam.contexts.WebSessionContext;
import org.jboss.seam.core.Manager;
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.authenticationFilter")
@Install(value = false, precedence = BUILT_IN)
@Intercept(NEVER)
@Filter(within = "org.jboss.seam.web.exceptionFilter")
public class AuthenticationFilter extends AbstractFilter
{
private static final String DEFAULT_REALM = "seamApp";
private static final String AUTH_TYPE_BASIC = "basic";
private static final String AUTH_TYPE_DIGEST = "digest";
@Logger Log log;
public enum AuthType {basic, digest}
private String realm = DEFAULT_REALM;
private String key;
private int nonceValiditySeconds = 300;
private String authType = AUTH_TYPE_BASIC;
public void setRealm(String realm)
{
this.realm = realm;
}
public String getRealm()
{
return realm;
}
public void setAuthType(String authType)
{
this.authType = authType;
}
public String getAuthType()
{
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
{
if (!(request instanceof HttpServletRequest))
{
throw new ServletException("This filter can only process HttpServletRequest requests");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (AUTH_TYPE_BASIC.equals(authType))
processBasicAuth(httpRequest, httpResponse, chain);
else if (AUTH_TYPE_DIGEST.equals(authType))
processDigestAuth(httpRequest, httpResponse, chain);
else
throw new ServletException("Invalid authentication type");
}
private void processBasicAuth(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws IOException, ServletException
{
Context ctx = new WebSessionContext(new ServletSessionImpl(request.getSession()));
Identity identity = (Identity) ctx.get(Identity.class);
boolean requireAuth = false;
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Basic "))
{
String base64Token = header.substring(6);
String token = new String(Base64.decode(base64Token));
String username = "";
String password = "";
int delim = token.indexOf(":");
if (delim != -1)
{
username = token.substring(0, delim);
password = token.substring(delim + 1);
}
// Only reauthenticate if username doesn't match Identity.username and user isn't authenticated
if (!username.equals(identity.getUsername()) || !identity.isLoggedIn())
{
identity.setUsername(username);
identity.setPassword(password);
}
}
if (!identity.isLoggedIn() && !identity.isCredentialsSet())
{
requireAuth = true;
}
try
{
if (!requireAuth)
{
chain.doFilter(request, response);
return;
}
}
catch (NotLoggedInException ex)
{
requireAuth = true;
}
if (requireAuth && !identity.isLoggedIn())
{
response.addHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not authorized");
}
}
private void processDigestAuth(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws IOException, ServletException
{
Context ctx = new WebSessionContext(new ServletSessionImpl(request.getSession()));
Identity identity = (Identity) ctx.get(Identity.class);
boolean requireAuth = false;
boolean nonceExpired = false;
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Digest "))
{
String section212response = header.substring(7);
String[] headerEntries = section212response.split(",");
Map<String,String> headerMap = new HashMap<String,String>();
for (String entry : headerEntries)
{
String[] vals = split(entry, "=");
headerMap.put(vals[0].trim(), vals[1].replace("\"", "").trim());
}
identity.setUsername(headerMap.get("username"));
DigestRequest digestRequest = new DigestRequest();
digestRequest.setHttpMethod(request.getMethod());
digestRequest.setSystemRealm(realm);
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);
authenticate(request, identity);
}
catch (DigestValidationException ex)
{
log.error(String.format("Digest validation failed, header [%s]: %s",
section212response, ex.getMessage()));
requireAuth = true;
if (ex.isNonceExpired()) nonceExpired = true;
}
catch (Exception ex)
{
log.error("Error authenticating: " + ex.getMessage());
requireAuth = true;
}
}
if (!identity.isLoggedIn() && !identity.isCredentialsSet())
{
requireAuth = true;
}
try
{
if (!requireAuth)
{
chain.doFilter(request, response);
return;
}
}
catch (NotLoggedInException ex)
{
requireAuth = true;
}
if (requireAuth && !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=\"" + realm + "\", " + "qop=\"auth\", nonce=\""
+ nonceValueBase64 + "\"";
if (nonceExpired) authenticateHeader = authenticateHeader + ", stale=\"true\"";
response.addHeader("WWW-Authenticate", authenticateHeader);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
private void authenticate(HttpServletRequest request, Identity identity)
throws Exception
{
try
{
HttpSession session = request.getSession(true);
Lifecycle.setPhaseId(PhaseId.INVOKE_APPLICATION);
Lifecycle.setServletRequest(request);
Lifecycle.beginRequest(getServletContext(), session, request);
Manager.instance().restoreConversation( request.getParameterMap() );
Lifecycle.resumeConversation(session);
Manager.instance().handleConversationPropagation( request.getParameterMap() );
identity.authenticate();
}
catch (Exception ex)
{
Lifecycle.endRequest();
throw ex;
}
finally
{
Lifecycle.setServletRequest(null);
Lifecycle.setPhaseId(null);
}
}
private String[] split(String toSplit, String delimiter)
{
if (delimiter.length() != 1) {
throw new IllegalArgumentException("Delimiter can only be one character in length");
}
int offset = toSplit.indexOf(delimiter);
if (offset < 0) {
return null;
}
String beforeDelimiter = toSplit.substring(0, offset);
String afterDelimiter = toSplit.substring(offset + 1);
return new String[] {beforeDelimiter, afterDelimiter};
}
}
More information about the jboss-cvs-commits
mailing list