Two realms in same application with Spring Security?

Viewed 10969

We're building a web application that is available to both authenticated and anonymous users. If you decide not to register/login you only have a limited set of features. User authentication is done over OpenID with Spring Security. That works fine.

However, the application also comes with an admin UI that is deployed at <host>/<context-root>/admin. Can we have two separate realms with Spring Security (e.g. basic auth for /admin/**)? How does that have to be configured?

3 Answers

Possible solution:

  • Add URL interceptor for /admin the requires "ROLE_ADMIN"
  • Configure instance of org.springframework.security.web.authentication.www.BasicAuthenticationFilter to intercept the /admin URL and authenticate user as ROLE_ADMIN if it provides the appropriate credentials

Sample configuration:

<security:intercept-url pattern="/admin" access="ROLE_ADMIN"/>

<bean id="basicAuthenticationEntryPoint" 
      class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
    <property name="realmName" 
              value="WS realm"/>
</bean>

<bean id="basicAuthenticationProcessingFilter"
      class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
    <property name="authenticationManager" 
              ref="authenticationManager"/>
    <property name="authenticationEntryPoint" 
              ref="basicAuthenticationEntryPoint"/>    
</bean>

Note: default implementation of BasicAuthenticationFilter is a passive filter, i.e. it just looks for a basic auth header in the request and if it is not present - does nothing. If you want the filter to explicitly require the basic authentication from the client, you need to extend the default implementation to commence to authentication entry point:

public class BasicAuthenticationFilter 
       extends org.springframework.security.web.authentication.www.BasicAuthenticationFilter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;

        String header = request.getHeader("Authorization");

        if ((header != null) && header.startsWith("Basic ")) {
            super.doFilter(req, res, chain);
        } else {
            getAuthenticationEntryPoint().commence(request, response, new AuthenticationCredentialsNotFoundException("Missing credentials"));
        }
    }
}

In addition, you need to tweak the filter to apply to /admin URL only - either by hard-coding this in doFilter method or by providing an appropriate wrapper bean.

Related