package com.bradmcevoy.http; import com.bradmcevoy.http.http11.auth.BasicAuthHandler; import com.bradmcevoy.http.http11.auth.DigestAuthenticationHandler; import com.bradmcevoy.http.http11.auth.NonceProvider; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author brad */ public class AuthenticationService { private static final Logger log = LoggerFactory.getLogger( AuthenticationService.class ); private List<AuthenticationHandler> authenticationHandlers; private boolean disableBasic; private boolean disableDigest; /** * Creates a AuthenticationService using the given handlers. Use this if * you don't want the default of a BasicAuthHandler and a DigestAuthenticationHandler * * @param authenticationHandlers */ public AuthenticationService( List<AuthenticationHandler> authenticationHandlers ) { this.authenticationHandlers = authenticationHandlers; } /** * Creates basic and digest handlers with the given NonceProvider * * @param nonceProvider */ public AuthenticationService( NonceProvider nonceProvider ) { AuthenticationHandler digest = new DigestAuthenticationHandler( nonceProvider ); AuthenticationHandler basic = new BasicAuthHandler(); authenticationHandlers = new ArrayList<AuthenticationHandler>(); authenticationHandlers.add( basic ); authenticationHandlers.add( digest ); } /** * Creates with Basic and Digest handlers * */ public AuthenticationService() { AuthenticationHandler digest = new DigestAuthenticationHandler(); AuthenticationHandler basic = new BasicAuthHandler(); authenticationHandlers = new ArrayList<AuthenticationHandler>(); authenticationHandlers.add( basic ); authenticationHandlers.add( digest ); } public void setDisableBasic( boolean b ) { if( b ) { Iterator<AuthenticationHandler> it = this.authenticationHandlers.iterator(); while( it.hasNext() ) { AuthenticationHandler hnd = it.next(); if( hnd instanceof BasicAuthHandler ) { it.remove(); } } } disableBasic = b; } public boolean isDisableBasic() { return disableBasic; } public void setDisableDigest( boolean b ) { if( b ) { Iterator<AuthenticationHandler> it = this.authenticationHandlers.iterator(); while( it.hasNext() ) { AuthenticationHandler hnd = it.next(); if( hnd instanceof DigestAuthenticationHandler ) { it.remove(); } } } disableDigest = b; } public boolean isDisableDigest() { return disableDigest; } /** * Looks for an AuthenticationHandler which supports the given resource and * authorization header, and then returns the result of that handler's * authenticate method. * * Returns null if no handlers support the request * * @param resource * @param request * @return */ public Object authenticate( Resource resource, Request request ) { for( AuthenticationHandler h : authenticationHandlers ) { if( h.supports( resource, request ) ) { Object o = h.authenticate( resource, request ); if( o == null ) { log.warn( "authentication failed by AuthenticationHandler:" + h.getClass() ); } return o; } } log.warn( "No AuthenticationHandler supports scheme:" + request.getAuthorization().getScheme() + " and resource type: " + resource.getClass() ); return null; } /** * Generates a list of http authentication challenges, one for each * supported authentication method, to be sent to the client. * * @param resource - the resoruce being requested * @param request - the current request * @return - a list of http challenges */ public List<String> getChallenges( Resource resource, Request request ) { List<String> challenges = new ArrayList<String>(); for( AuthenticationHandler h : authenticationHandlers ) { if( h.isCompatible( resource ) ) { log.debug( "challenge for auth: " + h.getClass() ); String ch = h.getChallenge( resource, request ); challenges.add( ch ); } else { log.debug( "not challenging for auth: " + h.getClass() + " for resource type: " + resource.getClass() ); } } return challenges; } public List<AuthenticationHandler> getAuthenticationHandlers() { return Collections.unmodifiableList( authenticationHandlers ); } }