/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package io.milton.http.http11.auth; import io.milton.http.AuthenticationHandler; import io.milton.http.Filter; import io.milton.http.FilterChain; import io.milton.http.Request; import io.milton.http.Response; import io.milton.http.http11.Http11ResponseHandler; import io.milton.http.SecurityManager; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A filter to perform authentication before resource location. * * This allows the authenticated context to be available for resource location. * * Note that this filter contains a list of AuthenticationHandler. However, * these handlers MUST be designed to ignore the resource variable as it will * always be null when used with this filter. This approach allows these handlers * to be used with the post-resource-location approach. * */ public class PreAuthenticationFilter implements Filter { private static final Logger log = LoggerFactory.getLogger( PreAuthenticationFilter.class ); private static final ThreadLocal<Request> tlRequest = new ThreadLocal<Request>(); private final Http11ResponseHandler responseHandler; private final List<AuthenticationHandler> authenticationHandlers; public static Request getCurrentRequest() { return tlRequest.get(); } public PreAuthenticationFilter( Http11ResponseHandler responseHandler, List<AuthenticationHandler> authenticationHandlers ) { this.responseHandler = responseHandler; this.authenticationHandlers = authenticationHandlers; } public PreAuthenticationFilter( Http11ResponseHandler responseHandler, SecurityManager securityManager ) { this.responseHandler = responseHandler; this.authenticationHandlers = new ArrayList<AuthenticationHandler>(); authenticationHandlers.add( new SecurityManagerBasicAuthHandler( securityManager ) ); authenticationHandlers.add( new SecurityManagerDigestAuthenticationHandler( securityManager ) ); } public PreAuthenticationFilter( Http11ResponseHandler responseHandler, SecurityManager securityManager, NonceProvider np) { this.responseHandler = responseHandler; this.authenticationHandlers = new ArrayList<AuthenticationHandler>(); authenticationHandlers.add( new SecurityManagerBasicAuthHandler( securityManager ) ); authenticationHandlers.add( new SecurityManagerDigestAuthenticationHandler( np, securityManager ) ); } @Override public void process( FilterChain chain, Request request, Response response ) { log.trace( "process" ); try { tlRequest.set( request ); Object authTag = authenticate( request ); if( authTag != null ) { request.getAuthorization().setTag( authTag ); chain.process( request, response ); } else { responseHandler.respondUnauthorised( null, response, request ); } } finally { tlRequest.remove(); } } /** * 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 request * @return */ public Object authenticate( Request request ) { for( AuthenticationHandler h : authenticationHandlers ) { if( h.supports( null, request ) ) { Object o = h.authenticate( null, request ); if( o == null ) { log.warn( "authentication failed by AuthenticationHandler:" + h.getClass() ); } return o; } } if( request.getAuthorization() == null ) { // note that this is completely normal, so just TRACE if( log.isTraceEnabled() ) { log.trace( "No AuthenticationHandler supports this request - no authorisation given in request" ); } } else { // authorisation was present in the request, but no handlers accepted it - probably a config problem if( log.isWarnEnabled() ) { log.warn( "No AuthenticationHandler supports this request with scheme:" + request.getAuthorization().getScheme() ); } } return null; } /** * Generates a list of http authentication challenges, one for each * supported authentication method, to be sent to the client. * * @param request - the current request * @return - a list of http challenges */ public List<String> getChallenges( Request request ) { List<String> challenges = new ArrayList<String>(); for( AuthenticationHandler h : authenticationHandlers ) { h.appendChallenges(null, request, challenges); } return challenges; } }