This document is a brief description of the processing that occurs to authenticate and authorize an HTTP request using Acegi and the SAIS Framework.
The HTTP request is intercepted in a servlet filter, that delegates to a collection of Acegi filters, called the filter chain. The filter chain ensures the sequence of authorization and authentication processing, and manages authentication protocols and access to security information about users. Upon successful authentication and authorization it establishes a SecurityContext for use by the application.
The filter chain is configured in the Spring Context, the servlet filter in web.xml. SAIS applications will use either Spring Context configurations for security will be in either applicationContext-common-security.xml or applicationContext-web.xml, located in src/main/resources of the application.
The configuration bean for the filter chain is called the filterChainProxy. Here is a sample configuration:
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> PATTERN_TYPE_APACHE_ANT /css/**=#NONE# /dhtml/**=#NONE# /images/**=#NONE# /js/**=#NONE# /**=httpSessionContextIntegrationFilter,exceptionTranslationFilter,ssoAuthenticationProcessingFilter,mitBasicProcessingFilter,filterSecurityInterceptor,switchUserProcessingFilter </value> </property> </bean>
The filter chain run order is defined on the line starting with "/**=httpSessionContextIntegrationFilter". The items in this list are also configured bean references. They perform the following functions:
httpSessionContextIntegrationFilter: Gets an existing security context from the session, or creates a new empty context.
exceptionTranslationFilter: catches all exceptions from the filters that follow. Applies configured exception handlers based on the exception type caught. For example, if an AuthenticationException is thrown, indicating that the request is not authenticated yet, then it calls the method to start the authentication process. If an AccessDeniedException is thrown, indicating that authentication has failed, then the AccessDeniedHandler is called. The default handler simply sends an access denies http response code in the response header.
ssoAuthenticationProcessingFilter: If authentication has not already been established in the SecurityContext ( that is was not present in the session ), checks to see if the user is already set in the servlet request, indicating that SSO has authenticated the user. If so, it sets up all the data structures needed by the security context. This includes the list of roles that the user is authorized for, based on the results of calling the configured authorization services ( see below ).
mitBasicProcessingFilter: If authentication has not already been established ( that is by either being present in the session or by SSO ), and the local authentication property has been set in the application property file, performs Basic authentication against the local credentials configured in the application property file. Basic authentication is a two step process that requires two requests. The first request that is unauthenticated will result in an AuthenticationException, which results in the start of the Basic authentication process, which sends a response with an authentication request in the header. Browsers interpret this to show the familiar ugly login box to the user. When the user submits the login credentials in what is now the second request, it contains a header with the credentials. The presence of this header is detected by the mitBasicProcessingFilter and the credentials are compared to the values from the property file. If there is a match the data structures for the security context are configured including the list of roles from the configured authorization services. However in this case the presence of role properties in the application property file will bypass the calls to the authorization services.
filterSecurityInterceptor: Secures the requested HTTP resource(s) based on the SecurityContext. The work is delegated to a number of helpers configured for this bean. Requires a definition of what resources are to be protected and what roles apply. If the requested resource is supposed to be protected and there is no established authentication in the SecurityContext by this point, it throws an AuthenticationException which is handled as described before. Otherwise, it will determine if authorization in the SecurityContext is sufficient for access to the resource, throwing AccessDeniedException if appropriate.
switchProcessingUserFilter: This is an optional filter that the allows a user to invoke a URL that lets them impersonate another user. Since access to this feature usually requires that the request be authorized for the URL resource that performs the switch, it follows the filterSecurityInterceptor in the chain. Once the switch is performed, the SecurityContext contains the credentials for a different user, but it also remembers the original user so impersonation may be exited and the original credentials restored.
The beans that determines which authorization services will be called to get the authenticated user's roles looks as follows:
<bean id="mitsisRolesUserDetailsService" class="edu.mit.common.security.acegi.userdetails.MitsisRolesUserDetailsService"> <property name="authorizationService" ref="authorizationService" /> </bean> <bean id="authorizationService" class="edu.mit.common.security.authorization.MultipleAuthorizationsService"> <property name="combine" value="false" /> <property name="authorizationServices"> <list> <ref bean="studentRoleAuthorizationService" /> <ref bean="mitRolesAuthorizationService" /> </list> </property> </bean>
mitsisRolesUserDetailsService: acts as an adapter between the Acegi security system and the authorization classes in the SAIS framework.