this.resourceManager = checkNotNull( "resourceManager", resourceManager );
}
@Override
public Subject authenticate( final SecurityContext context ) throws AuthenticationException {
final HttpSecurityContext httpContext = checkInstanceOf( "context", context, HttpSecurityContext.class );
Principal principal = null;
for ( final AuthenticatedStorageProvider storeProvider : authStorageProviders ) {
principal = storeProvider.load( httpContext );
if ( principal != null ) {
break;
}
}
if ( principal != null && principal instanceof Subject ) {
return (Subject) principal;
}
boolean isRememberOp = principal != null;
final boolean requiresAuthentication = resourceManager.requiresAuthentication( httpContext.getResource() );
if ( principal == null ) {
for ( final AuthenticationScheme authScheme : authSchemes ) {
if ( authScheme.isAuthenticationRequest( httpContext ) ) {
break;
} else if ( requiresAuthentication ) {
if ( !requestCache.containsKey( httpContext.getRequest().getSession().getId() ) ) {
String preservedQueryStr = httpContext.getRequest().getQueryString();
if ( preservedQueryStr == null ) {
preservedQueryStr = "";
} else {
preservedQueryStr = "?" + preservedQueryStr;
}
// this is for the benefit of dev mode logins: the uf_security_check form
// won't have the gwt.codeserver parameter on it, but the referer will
String referer = httpContext.getRequest().getHeader( "Referer" );
if ( preservedQueryStr.equals( "" ) && referer != null && referer.indexOf( '?' ) >= 0 ) {
preservedQueryStr = referer.substring( referer.indexOf( '?' ) );
}
if ( forceURL != null ) {
// prepend context path for context-relative forceURLs
String contextPrefix = "";
if ( forceURL.startsWith( "/" ) ) {
contextPrefix = httpContext.getRequest().getContextPath();
}
requestCache.put( httpContext.getRequest().getSession().getId(), contextPrefix + forceURL + preservedQueryStr );
} else {
requestCache.put( httpContext.getRequest().getSession().getId(), httpContext.getRequest().getRequestURI() + preservedQueryStr );
}
}
authScheme.challengeClient( httpContext );
}
}
if ( !requiresAuthentication ) {
return null;
}
all_auth:
for ( final AuthenticationScheme authScheme : authSchemes ) {
final Credential credential = authScheme.buildCredential( httpContext );
if ( credential == null ) {
continue;
}
for ( final AuthenticationProvider authProvider : authProviders ) {
final AuthenticationResult result = authProvider.authenticate( credential, context );
if ( result.getStatus().equals( FAILED ) ) {
authScheme.challengeClient( httpContext );
throw new AuthenticationException( "Invalid credentials." );
} else if ( result.getStatus().equals( SUCCESS ) ) {
principal = result.getPrincipal();
break all_auth;
}
}
}
}
if ( principal == null ) {
throw new AuthenticationException( "Invalid credentials." );
}
final List<Role> roles = new ArrayList<Role>();
if ( isRememberOp ) {
roles.add( new RoleImpl( ROLE_REMEMBER_ME ) );
}
for ( final RoleProvider roleProvider : roleProviders ) {
roles.addAll( roleProvider.loadRoles( principal, context ) );
}
final Map<String, String> properties = new HashMap<String, String>();
for ( final SubjectPropertiesProvider propertiesProvider : subjectPropertiesProviders ) {
properties.putAll( propertiesProvider.loadProperties( principal ) );
}
final String name = principal.getName();
final Subject result = new IdentityImpl( name, roles, properties );
for ( final AuthenticatedStorageProvider storeProvider : authStorageProviders ) {
storeProvider.store( httpContext, result );
}
final String originalRequest = requestCache.remove( httpContext.getRequest().getSession().getId() );
if ( originalRequest != null && !originalRequest.isEmpty() && !httpContext.getResponse().isCommitted() ) {
try {
if ( useRedirect( originalRequest ) ) {
httpContext.getResponse().sendRedirect( originalRequest );
} else {
// subject must be already set here since we forwarding
SecurityFactory.setSubject( result );
RequestDispatcher rd = httpContext.getRequest().getRequestDispatcher( originalRequest.replaceFirst( httpContext.getRequest().getContextPath(), "" ) );
// forward instead of sendRedirect as sendRedirect will always use GET method which
// means it can change http method if non GET was used for instance POST
rd.forward( httpContext.getRequest(), httpContext.getResponse() );
}
} catch ( Exception e ) {
throw new RuntimeException( "Unable to redirect.", e );
}
}