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

org.springframework.security.config.annotation.web.configurers.LogoutConfigurer Maven / Gradle / Ivy

There is a newer version: 6.2.4
Show newest version
/*
 * Copyright 2002-2019 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.config.annotation.web.configurers;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.security.config.annotation.SecurityConfigurer;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
import org.springframework.security.web.authentication.logout.DelegatingLogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;

/**
 * Adds logout support. Other {@link SecurityConfigurer} instances may invoke
 * {@link #addLogoutHandler(LogoutHandler)} in the {@link #init(HttpSecurityBuilder)}
 * phase.
 *
 * 

Security Filters

* * The following Filters are populated * *
    *
  • {@link LogoutFilter}
  • *
* *

Shared Objects Created

* * No shared Objects are created * *

Shared Objects Used

* * No shared objects are used. * * @author Rob Winch * @author Onur Kagan Ozcan * @since 3.2 * @see RememberMeConfigurer */ public final class LogoutConfigurer> extends AbstractHttpConfigurer, H> { private List logoutHandlers = new ArrayList<>(); private SecurityContextLogoutHandler contextLogoutHandler = new SecurityContextLogoutHandler(); private String logoutSuccessUrl = "/login?logout"; private LogoutSuccessHandler logoutSuccessHandler; private String logoutUrl = "/logout"; private RequestMatcher logoutRequestMatcher; private boolean permitAll; private boolean customLogoutSuccess; private LinkedHashMap defaultLogoutSuccessHandlerMappings = new LinkedHashMap<>(); /** * Creates a new instance * @see HttpSecurity#logout() */ public LogoutConfigurer() { } /** * Adds a {@link LogoutHandler}. {@link SecurityContextLogoutHandler} and * {@link LogoutSuccessEventPublishingLogoutHandler} are added as last * {@link LogoutHandler} instances by default. * @param logoutHandler the {@link LogoutHandler} to add * @return the {@link LogoutConfigurer} for further customization */ public LogoutConfigurer addLogoutHandler(LogoutHandler logoutHandler) { Assert.notNull(logoutHandler, "logoutHandler cannot be null"); this.logoutHandlers.add(logoutHandler); return this; } /** * Specifies if {@link SecurityContextLogoutHandler} should clear the * {@link Authentication} at the time of logout. * @param clearAuthentication true {@link SecurityContextLogoutHandler} should clear * the {@link Authentication} (default), or false otherwise. * @return the {@link LogoutConfigurer} for further customization */ public LogoutConfigurer clearAuthentication(boolean clearAuthentication) { this.contextLogoutHandler.setClearAuthentication(clearAuthentication); return this; } /** * Configures {@link SecurityContextLogoutHandler} to invalidate the * {@link HttpSession} at the time of logout. * @param invalidateHttpSession true if the {@link HttpSession} should be invalidated * (default), or false otherwise. * @return the {@link LogoutConfigurer} for further customization */ public LogoutConfigurer invalidateHttpSession(boolean invalidateHttpSession) { this.contextLogoutHandler.setInvalidateHttpSession(invalidateHttpSession); return this; } /** * The URL that triggers log out to occur (default is "/logout"). If CSRF protection * is enabled (default), then the request must also be a POST. This means that by * default POST "/logout" is required to trigger a log out. If CSRF protection is * disabled, then any HTTP method is allowed. * *

* It is considered best practice to use an HTTP POST on any action that changes state * (i.e. log out) to protect against * CSRF * attacks. If you really want to use an HTTP GET, you can use * logoutRequestMatcher(new AntPathRequestMatcher(logoutUrl, "GET")); *

* @param logoutUrl the URL that will invoke logout. * @return the {@link LogoutConfigurer} for further customization * @see #logoutRequestMatcher(RequestMatcher) * @see HttpSecurity#csrf() */ public LogoutConfigurer logoutUrl(String logoutUrl) { this.logoutRequestMatcher = null; this.logoutUrl = logoutUrl; return this; } /** * The RequestMatcher that triggers log out to occur. In most circumstances users will * use {@link #logoutUrl(String)} which helps enforce good practices. * @param logoutRequestMatcher the RequestMatcher used to determine if logout should * occur. * @return the {@link LogoutConfigurer} for further customization * @see #logoutUrl(String) */ public LogoutConfigurer logoutRequestMatcher(RequestMatcher logoutRequestMatcher) { this.logoutRequestMatcher = logoutRequestMatcher; return this; } /** * The URL to redirect to after logout has occurred. The default is "/login?logout". * This is a shortcut for invoking {@link #logoutSuccessHandler(LogoutSuccessHandler)} * with a {@link SimpleUrlLogoutSuccessHandler}. * @param logoutSuccessUrl the URL to redirect to after logout occurred * @return the {@link LogoutConfigurer} for further customization */ public LogoutConfigurer logoutSuccessUrl(String logoutSuccessUrl) { this.customLogoutSuccess = true; this.logoutSuccessUrl = logoutSuccessUrl; return this; } /** * A shortcut for {@link #permitAll(boolean)} with true as an argument. * @return the {@link LogoutConfigurer} for further customizations */ public LogoutConfigurer permitAll() { return permitAll(true); } /** * Allows specifying the names of cookies to be removed on logout success. This is a * shortcut to easily invoke {@link #addLogoutHandler(LogoutHandler)} with a * {@link CookieClearingLogoutHandler}. * @param cookieNamesToClear the names of cookies to be removed on logout success. * @return the {@link LogoutConfigurer} for further customization */ public LogoutConfigurer deleteCookies(String... cookieNamesToClear) { return addLogoutHandler(new CookieClearingLogoutHandler(cookieNamesToClear)); } /** * Sets the {@link LogoutSuccessHandler} to use. If this is specified, * {@link #logoutSuccessUrl(String)} is ignored. * @param logoutSuccessHandler the {@link LogoutSuccessHandler} to use after a user * has been logged out. * @return the {@link LogoutConfigurer} for further customizations */ public LogoutConfigurer logoutSuccessHandler(LogoutSuccessHandler logoutSuccessHandler) { this.logoutSuccessUrl = null; this.customLogoutSuccess = true; this.logoutSuccessHandler = logoutSuccessHandler; return this; } /** * Sets a default {@link LogoutSuccessHandler} to be used which prefers being invoked * for the provided {@link RequestMatcher}. If no {@link LogoutSuccessHandler} is * specified a {@link SimpleUrlLogoutSuccessHandler} will be used. If any default * {@link LogoutSuccessHandler} instances are configured, then a * {@link DelegatingLogoutSuccessHandler} will be used that defaults to a * {@link SimpleUrlLogoutSuccessHandler}. * @param handler the {@link LogoutSuccessHandler} to use * @param preferredMatcher the {@link RequestMatcher} for this default * {@link LogoutSuccessHandler} * @return the {@link LogoutConfigurer} for further customizations */ public LogoutConfigurer defaultLogoutSuccessHandlerFor(LogoutSuccessHandler handler, RequestMatcher preferredMatcher) { Assert.notNull(handler, "handler cannot be null"); Assert.notNull(preferredMatcher, "preferredMatcher cannot be null"); this.defaultLogoutSuccessHandlerMappings.put(preferredMatcher, handler); return this; } /** * Grants access to the {@link #logoutSuccessUrl(String)} and the * {@link #logoutUrl(String)} for every user. * @param permitAll if true grants access, else nothing is done * @return the {@link LogoutConfigurer} for further customization. */ public LogoutConfigurer permitAll(boolean permitAll) { this.permitAll = permitAll; return this; } /** * Gets the {@link LogoutSuccessHandler} if not null, otherwise creates a new * {@link SimpleUrlLogoutSuccessHandler} using the {@link #logoutSuccessUrl(String)}. * @return the {@link LogoutSuccessHandler} to use */ private LogoutSuccessHandler getLogoutSuccessHandler() { LogoutSuccessHandler handler = this.logoutSuccessHandler; if (handler == null) { handler = createDefaultSuccessHandler(); } return handler; } private LogoutSuccessHandler createDefaultSuccessHandler() { SimpleUrlLogoutSuccessHandler urlLogoutHandler = new SimpleUrlLogoutSuccessHandler(); urlLogoutHandler.setDefaultTargetUrl(this.logoutSuccessUrl); if (this.defaultLogoutSuccessHandlerMappings.isEmpty()) { return urlLogoutHandler; } DelegatingLogoutSuccessHandler successHandler = new DelegatingLogoutSuccessHandler( this.defaultLogoutSuccessHandlerMappings); successHandler.setDefaultLogoutSuccessHandler(urlLogoutHandler); return successHandler; } @Override public void init(H http) { if (this.permitAll) { PermitAllSupport.permitAll(http, this.logoutSuccessUrl); PermitAllSupport.permitAll(http, this.getLogoutRequestMatcher(http)); } DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http .getSharedObject(DefaultLoginPageGeneratingFilter.class); if (loginPageGeneratingFilter != null && !isCustomLogoutSuccess()) { loginPageGeneratingFilter.setLogoutSuccessUrl(getLogoutSuccessUrl()); } } @Override public void configure(H http) throws Exception { LogoutFilter logoutFilter = createLogoutFilter(http); http.addFilter(logoutFilter); } /** * Returns true if the logout success has been customized via * {@link #logoutSuccessUrl(String)} or * {@link #logoutSuccessHandler(LogoutSuccessHandler)}. * @return true if logout success handling has been customized, else false */ boolean isCustomLogoutSuccess() { return this.customLogoutSuccess; } /** * Gets the logoutSuccesUrl or null if a * {@link #logoutSuccessHandler(LogoutSuccessHandler)} was configured. * @return the logoutSuccessUrl */ private String getLogoutSuccessUrl() { return this.logoutSuccessUrl; } /** * Gets the {@link LogoutHandler} instances that will be used. * @return the {@link LogoutHandler} instances. Cannot be null. */ List getLogoutHandlers() { return this.logoutHandlers; } /** * Creates the {@link LogoutFilter} using the {@link LogoutHandler} instances, the * {@link #logoutSuccessHandler(LogoutSuccessHandler)} and the * {@link #logoutUrl(String)}. * @param http the builder to use * @return the {@link LogoutFilter} to use. */ private LogoutFilter createLogoutFilter(H http) { this.logoutHandlers.add(this.contextLogoutHandler); this.logoutHandlers.add(postProcess(new LogoutSuccessEventPublishingLogoutHandler())); LogoutHandler[] handlers = this.logoutHandlers.toArray(new LogoutHandler[0]); LogoutFilter result = new LogoutFilter(getLogoutSuccessHandler(), handlers); result.setLogoutRequestMatcher(getLogoutRequestMatcher(http)); result = postProcess(result); return result; } private RequestMatcher getLogoutRequestMatcher(H http) { if (this.logoutRequestMatcher != null) { return this.logoutRequestMatcher; } this.logoutRequestMatcher = createLogoutRequestMatcher(http); return this.logoutRequestMatcher; } @SuppressWarnings("unchecked") private RequestMatcher createLogoutRequestMatcher(H http) { RequestMatcher post = createLogoutRequestMatcher("POST"); if (http.getConfigurer(CsrfConfigurer.class) != null) { return post; } RequestMatcher get = createLogoutRequestMatcher("GET"); RequestMatcher put = createLogoutRequestMatcher("PUT"); RequestMatcher delete = createLogoutRequestMatcher("DELETE"); return new OrRequestMatcher(get, post, put, delete); } private RequestMatcher createLogoutRequestMatcher(String httpMethod) { return new AntPathRequestMatcher(this.logoutUrl, httpMethod); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy