All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.security.authentication.DefaultAuthenticationEventPublisher Maven / Gradle / Ivy

There is a newer version: 6.3.3
Show newest version
/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed 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
 *
 *      https://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 org.springframework.security.authentication;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent;
import org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent;
import org.springframework.security.authentication.event.AuthenticationFailureExpiredEvent;
import org.springframework.security.authentication.event.AuthenticationFailureLockedEvent;
import org.springframework.security.authentication.event.AuthenticationFailureProviderNotFoundEvent;
import org.springframework.security.authentication.event.AuthenticationFailureProxyUntrustedEvent;
import org.springframework.security.authentication.event.AuthenticationFailureServiceExceptionEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;

/**
 * The default strategy for publishing authentication events.
 * 

* Maps well-known AuthenticationException types to events and publishes them via * the application context. If configured as a bean, it will pick up the * ApplicationEventPublisher automatically. Otherwise, the constructor which * takes the publisher as an argument should be used. *

* The exception-mapping system can be fine-tuned by setting the * additionalExceptionMappings as a java.util.Properties object. In * the properties object, each of the keys represent the fully qualified classname of the * exception, and each of the values represent the name of an event class which subclasses * {@link org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent} * and provides its constructor. The additionalExceptionMappings will be merged * with the default ones. * * @author Luke Taylor * @since 3.0 */ public class DefaultAuthenticationEventPublisher implements AuthenticationEventPublisher, ApplicationEventPublisherAware { private final Log logger = LogFactory.getLog(getClass()); private ApplicationEventPublisher applicationEventPublisher; private final HashMap> exceptionMappings = new HashMap<>(); private Constructor defaultAuthenticationFailureEventConstructor; public DefaultAuthenticationEventPublisher() { this(null); } public DefaultAuthenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; addMapping(BadCredentialsException.class.getName(), AuthenticationFailureBadCredentialsEvent.class); addMapping(UsernameNotFoundException.class.getName(), AuthenticationFailureBadCredentialsEvent.class); addMapping(AccountExpiredException.class.getName(), AuthenticationFailureExpiredEvent.class); addMapping(ProviderNotFoundException.class.getName(), AuthenticationFailureProviderNotFoundEvent.class); addMapping(DisabledException.class.getName(), AuthenticationFailureDisabledEvent.class); addMapping(LockedException.class.getName(), AuthenticationFailureLockedEvent.class); addMapping(AuthenticationServiceException.class.getName(), AuthenticationFailureServiceExceptionEvent.class); addMapping(CredentialsExpiredException.class.getName(), AuthenticationFailureCredentialsExpiredEvent.class); addMapping("org.springframework.security.authentication.cas.ProxyUntrustedException", AuthenticationFailureProxyUntrustedEvent.class); addMapping("org.springframework.security.oauth2.server.resource.InvalidBearerTokenException", AuthenticationFailureBadCredentialsEvent.class); } @Override public void publishAuthenticationSuccess(Authentication authentication) { if (this.applicationEventPublisher != null) { this.applicationEventPublisher.publishEvent(new AuthenticationSuccessEvent(authentication)); } } @Override public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) { Constructor constructor = getEventConstructor(exception); AbstractAuthenticationEvent event = null; if (constructor != null) { try { event = constructor.newInstance(authentication, exception); } catch (IllegalAccessException | InvocationTargetException | InstantiationException ignored) { } } if (event != null) { if (this.applicationEventPublisher != null) { this.applicationEventPublisher.publishEvent(event); } } else { if (this.logger.isDebugEnabled()) { this.logger.debug("No event was found for the exception " + exception.getClass().getName()); } } } private Constructor getEventConstructor(AuthenticationException exception) { Constructor eventConstructor = this.exceptionMappings .get(exception.getClass().getName()); return (eventConstructor != null) ? eventConstructor : this.defaultAuthenticationFailureEventConstructor; } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } /** * Sets additional exception to event mappings. These are automatically merged with * the default exception to event mappings that ProviderManager defines. * @param additionalExceptionMappings where keys are the fully-qualified string name * of the exception class and the values are the fully-qualified string name of the * event class to fire. * @deprecated use {@link #setAdditionalExceptionMappings(Map)} */ @Deprecated @SuppressWarnings({ "unchecked" }) public void setAdditionalExceptionMappings(Properties additionalExceptionMappings) { Assert.notNull(additionalExceptionMappings, "The exceptionMappings object must not be null"); for (Object exceptionClass : additionalExceptionMappings.keySet()) { String eventClass = (String) additionalExceptionMappings.get(exceptionClass); try { Class clazz = getClass().getClassLoader().loadClass(eventClass); Assert.isAssignable(AbstractAuthenticationFailureEvent.class, clazz); addMapping((String) exceptionClass, (Class) clazz); } catch (ClassNotFoundException ex) { throw new RuntimeException("Failed to load authentication event class " + eventClass); } } } /** * Sets additional exception to event mappings. These are automatically merged with * the default exception to event mappings that ProviderManager defines. * @param mappings where keys are exception classes and values are event classes. * @since 5.3 */ public void setAdditionalExceptionMappings( Map, Class> mappings) { Assert.notEmpty(mappings, "The mappings Map must not be empty nor null"); for (Map.Entry, Class> entry : mappings .entrySet()) { Class exceptionClass = entry.getKey(); Class eventClass = entry.getValue(); Assert.notNull(exceptionClass, "exceptionClass cannot be null"); Assert.notNull(eventClass, "eventClass cannot be null"); addMapping(exceptionClass.getName(), (Class) eventClass); } } /** * Sets a default authentication failure event as a fallback event for any unmapped * exceptions not mapped in the exception mappings. * @param defaultAuthenticationFailureEventClass is the authentication failure event * class to be fired for unmapped exceptions. */ public void setDefaultAuthenticationFailureEvent( Class defaultAuthenticationFailureEventClass) { Assert.notNull(defaultAuthenticationFailureEventClass, "defaultAuthenticationFailureEventClass must not be null"); try { this.defaultAuthenticationFailureEventConstructor = defaultAuthenticationFailureEventClass .getConstructor(Authentication.class, AuthenticationException.class); } catch (NoSuchMethodException ex) { throw new RuntimeException("Default Authentication Failure event class " + defaultAuthenticationFailureEventClass.getName() + " has no suitable constructor"); } } private void addMapping(String exceptionClass, Class eventClass) { try { Constructor constructor = eventClass .getConstructor(Authentication.class, AuthenticationException.class); this.exceptionMappings.put(exceptionClass, constructor); } catch (NoSuchMethodException ex) { throw new RuntimeException( "Authentication event class " + eventClass.getName() + " has no suitable constructor"); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy