mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-12 21:33:30 +00:00
One Time Token login registers the default login page
closes gh-16414 Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
This commit is contained in:
parent
5ee6b83953
commit
238f47ce5e
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2024 the original author or authors.
|
* Copyright 2002-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -23,7 +23,6 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
import org.springframework.security.authentication.ott.GenerateOneTimeTokenRequest;
|
import org.springframework.security.authentication.ott.GenerateOneTimeTokenRequest;
|
||||||
import org.springframework.security.authentication.ott.InMemoryOneTimeTokenService;
|
import org.springframework.security.authentication.ott.InMemoryOneTimeTokenService;
|
||||||
@ -32,6 +31,9 @@ import org.springframework.security.authentication.ott.OneTimeTokenAuthenticatio
|
|||||||
import org.springframework.security.authentication.ott.OneTimeTokenService;
|
import org.springframework.security.authentication.ott.OneTimeTokenService;
|
||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
@ -49,34 +51,70 @@ import org.springframework.security.web.authentication.ott.OneTimeTokenGeneratio
|
|||||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||||
import org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter;
|
import org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter;
|
||||||
import org.springframework.security.web.authentication.ui.DefaultResourcesFilter;
|
import org.springframework.security.web.authentication.ui.DefaultResourcesFilter;
|
||||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
|
||||||
import org.springframework.security.web.context.SecurityContextRepository;
|
|
||||||
import org.springframework.security.web.csrf.CsrfToken;
|
import org.springframework.security.web.csrf.CsrfToken;
|
||||||
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
|
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
|
||||||
|
|
||||||
public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
/**
|
||||||
extends AbstractHttpConfigurer<OneTimeTokenLoginConfigurer<H>, H> {
|
* An {@link AbstractHttpConfigurer} for One-Time Token Login.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* One-Time Token Login provides an application with the capability to have users log in
|
||||||
|
* by obtaining a single-use token out of band, for example through email.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Defaults are provided for all configuration options, with the only required
|
||||||
|
* configuration being
|
||||||
|
* {@link #tokenGenerationSuccessHandler(OneTimeTokenGenerationSuccessHandler)}.
|
||||||
|
* Alternatively, a {@link OneTimeTokenGenerationSuccessHandler} {@code @Bean} may be
|
||||||
|
* registered instead.
|
||||||
|
*
|
||||||
|
* <h2>Security Filters</h2>
|
||||||
|
*
|
||||||
|
* The following {@code Filter}s are populated:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link DefaultOneTimeTokenSubmitPageGeneratingFilter}</li>
|
||||||
|
* <li>{@link GenerateOneTimeTokenFilter}</li>
|
||||||
|
* <li>{@link OneTimeTokenAuthenticationFilter}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <h2>Shared Objects Used</h2>
|
||||||
|
*
|
||||||
|
* The following shared objects are used:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link DefaultLoginPageGeneratingFilter} - if {@link #loginPage(String)} is not
|
||||||
|
* configured and {@code DefaultLoginPageGeneratingFilter} is available, then a default
|
||||||
|
* login page will be made available</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @author Daniel Garnier-Moiroux
|
||||||
|
* @since 6.4
|
||||||
|
* @see HttpSecurity#oneTimeTokenLogin(Customizer)
|
||||||
|
* @see DefaultOneTimeTokenSubmitPageGeneratingFilter
|
||||||
|
* @see GenerateOneTimeTokenFilter
|
||||||
|
* @see OneTimeTokenAuthenticationFilter
|
||||||
|
* @see AbstractAuthenticationFilterConfigurer
|
||||||
|
*/
|
||||||
|
public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||||
|
AbstractAuthenticationFilterConfigurer<H, OneTimeTokenLoginConfigurer<H>, OneTimeTokenAuthenticationFilter> {
|
||||||
|
|
||||||
private final ApplicationContext context;
|
private final ApplicationContext context;
|
||||||
|
|
||||||
private OneTimeTokenService oneTimeTokenService;
|
private OneTimeTokenService oneTimeTokenService;
|
||||||
|
|
||||||
private AuthenticationConverter authenticationConverter = new OneTimeTokenAuthenticationConverter();
|
private String defaultSubmitPageUrl = DefaultOneTimeTokenSubmitPageGeneratingFilter.DEFAULT_SUBMIT_PAGE_URL;
|
||||||
|
|
||||||
private AuthenticationFailureHandler authenticationFailureHandler;
|
|
||||||
|
|
||||||
private AuthenticationSuccessHandler authenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();
|
|
||||||
|
|
||||||
private String defaultSubmitPageUrl = "/login/ott";
|
|
||||||
|
|
||||||
private boolean submitPageEnabled = true;
|
private boolean submitPageEnabled = true;
|
||||||
|
|
||||||
private String loginProcessingUrl = OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL;
|
private String loginProcessingUrl = OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL;
|
||||||
|
|
||||||
private String tokenGeneratingUrl = "/ott/generate";
|
private String tokenGeneratingUrl = GenerateOneTimeTokenFilter.DEFAULT_GENERATE_URL;
|
||||||
|
|
||||||
private OneTimeTokenGenerationSuccessHandler oneTimeTokenGenerationSuccessHandler;
|
private OneTimeTokenGenerationSuccessHandler oneTimeTokenGenerationSuccessHandler;
|
||||||
|
|
||||||
@ -85,58 +123,41 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
private GenerateOneTimeTokenRequestResolver requestResolver;
|
private GenerateOneTimeTokenRequestResolver requestResolver;
|
||||||
|
|
||||||
public OneTimeTokenLoginConfigurer(ApplicationContext context) {
|
public OneTimeTokenLoginConfigurer(ApplicationContext context) {
|
||||||
|
super(new OneTimeTokenAuthenticationFilter(), OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(H http) {
|
public void init(H http) throws Exception {
|
||||||
|
super.init(http);
|
||||||
AuthenticationProvider authenticationProvider = getAuthenticationProvider();
|
AuthenticationProvider authenticationProvider = getAuthenticationProvider();
|
||||||
http.authenticationProvider(postProcess(authenticationProvider));
|
http.authenticationProvider(postProcess(authenticationProvider));
|
||||||
configureDefaultLoginPage(http);
|
intiDefaultLoginFilter(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureDefaultLoginPage(H http) {
|
private void intiDefaultLoginFilter(H http) {
|
||||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http
|
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http
|
||||||
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||||
if (loginPageGeneratingFilter == null) {
|
if (loginPageGeneratingFilter == null || isCustomLoginPage()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loginPageGeneratingFilter.setOneTimeTokenEnabled(true);
|
loginPageGeneratingFilter.setOneTimeTokenEnabled(true);
|
||||||
loginPageGeneratingFilter.setOneTimeTokenGenerationUrl(this.tokenGeneratingUrl);
|
loginPageGeneratingFilter.setOneTimeTokenGenerationUrl(this.tokenGeneratingUrl);
|
||||||
if (this.authenticationFailureHandler == null
|
|
||||||
&& StringUtils.hasText(loginPageGeneratingFilter.getLoginPageUrl())) {
|
if (!StringUtils.hasText(loginPageGeneratingFilter.getLoginPageUrl())) {
|
||||||
this.authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler(
|
loginPageGeneratingFilter.setLoginPageUrl(DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL);
|
||||||
loginPageGeneratingFilter.getLoginPageUrl() + "?error");
|
loginPageGeneratingFilter.setFailureUrl(DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL + "?"
|
||||||
|
+ DefaultLoginPageGeneratingFilter.ERROR_PARAMETER_NAME);
|
||||||
|
loginPageGeneratingFilter
|
||||||
|
.setLogoutSuccessUrl(DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL + "?logout");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(H http) {
|
public void configure(H http) throws Exception {
|
||||||
|
super.configure(http);
|
||||||
configureSubmitPage(http);
|
configureSubmitPage(http);
|
||||||
configureOttGenerateFilter(http);
|
configureOttGenerateFilter(http);
|
||||||
configureOttAuthenticationFilter(http);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureOttAuthenticationFilter(H http) {
|
|
||||||
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
|
|
||||||
OneTimeTokenAuthenticationFilter oneTimeTokenAuthenticationFilter = new OneTimeTokenAuthenticationFilter();
|
|
||||||
oneTimeTokenAuthenticationFilter.setAuthenticationManager(authenticationManager);
|
|
||||||
if (this.loginProcessingUrl != null) {
|
|
||||||
oneTimeTokenAuthenticationFilter
|
|
||||||
.setRequiresAuthenticationRequestMatcher(antMatcher(HttpMethod.POST, this.loginProcessingUrl));
|
|
||||||
}
|
|
||||||
oneTimeTokenAuthenticationFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
|
|
||||||
oneTimeTokenAuthenticationFilter.setAuthenticationFailureHandler(getAuthenticationFailureHandler());
|
|
||||||
oneTimeTokenAuthenticationFilter.setSecurityContextRepository(getSecurityContextRepository(http));
|
|
||||||
http.addFilter(postProcess(oneTimeTokenAuthenticationFilter));
|
|
||||||
}
|
|
||||||
|
|
||||||
private SecurityContextRepository getSecurityContextRepository(H http) {
|
|
||||||
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
|
||||||
if (securityContextRepository != null) {
|
|
||||||
return securityContextRepository;
|
|
||||||
}
|
|
||||||
return new HttpSessionSecurityContextRepository();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureOttGenerateFilter(H http) {
|
private void configureOttGenerateFilter(H http) {
|
||||||
@ -170,7 +191,7 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
DefaultOneTimeTokenSubmitPageGeneratingFilter submitPage = new DefaultOneTimeTokenSubmitPageGeneratingFilter();
|
DefaultOneTimeTokenSubmitPageGeneratingFilter submitPage = new DefaultOneTimeTokenSubmitPageGeneratingFilter();
|
||||||
submitPage.setResolveHiddenInputs(this::hiddenInputs);
|
submitPage.setResolveHiddenInputs(this::hiddenInputs);
|
||||||
submitPage.setRequestMatcher(antMatcher(HttpMethod.GET, this.defaultSubmitPageUrl));
|
submitPage.setRequestMatcher(antMatcher(HttpMethod.GET, this.defaultSubmitPageUrl));
|
||||||
submitPage.setLoginProcessingUrl(this.loginProcessingUrl);
|
submitPage.setLoginProcessingUrl(this.getLoginProcessingUrl());
|
||||||
http.addFilter(postProcess(submitPage));
|
http.addFilter(postProcess(submitPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +205,11 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this.authenticationProvider;
|
return this.authenticationProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
||||||
|
return antMatcher(HttpMethod.POST, loginProcessingUrl);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the {@link AuthenticationProvider} to use when authenticating the user.
|
* Specifies the {@link AuthenticationProvider} to use when authenticating the user.
|
||||||
* @param authenticationProvider
|
* @param authenticationProvider
|
||||||
@ -221,14 +247,25 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
* Only POST requests are processed, for that reason make sure that you pass a valid
|
* Only POST requests are processed, for that reason make sure that you pass a valid
|
||||||
* CSRF token if CSRF protection is enabled.
|
* CSRF token if CSRF protection is enabled.
|
||||||
* @param loginProcessingUrl
|
* @param loginProcessingUrl
|
||||||
* @see org.springframework.security.config.annotation.web.builders.HttpSecurity#csrf(Customizer)
|
* @see HttpSecurity#csrf(Customizer)
|
||||||
*/
|
*/
|
||||||
public OneTimeTokenLoginConfigurer<H> loginProcessingUrl(String loginProcessingUrl) {
|
public OneTimeTokenLoginConfigurer<H> loginProcessingUrl(String loginProcessingUrl) {
|
||||||
Assert.hasText(loginProcessingUrl, "loginProcessingUrl cannot be null or empty");
|
Assert.hasText(loginProcessingUrl, "loginProcessingUrl cannot be null or empty");
|
||||||
this.loginProcessingUrl = loginProcessingUrl;
|
super.loginProcessingUrl(loginProcessingUrl);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the URL to send users to if login is required. If used with
|
||||||
|
* {@link EnableWebSecurity} a default login page will be generated when this
|
||||||
|
* attribute is not specified.
|
||||||
|
* @param loginPage
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public OneTimeTokenLoginConfigurer<H> loginPage(String loginPage) {
|
||||||
|
return super.loginPage(loginPage);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures whether the default one-time token submit page should be shown. This
|
* Configures whether the default one-time token submit page should be shown. This
|
||||||
* will prevent the {@link DefaultOneTimeTokenSubmitPageGeneratingFilter} to be
|
* will prevent the {@link DefaultOneTimeTokenSubmitPageGeneratingFilter} to be
|
||||||
@ -273,7 +310,7 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*/
|
*/
|
||||||
public OneTimeTokenLoginConfigurer<H> authenticationConverter(AuthenticationConverter authenticationConverter) {
|
public OneTimeTokenLoginConfigurer<H> authenticationConverter(AuthenticationConverter authenticationConverter) {
|
||||||
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
|
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
|
||||||
this.authenticationConverter = authenticationConverter;
|
this.getAuthenticationFilter().setAuthenticationConverter(authenticationConverter);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,11 +320,13 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
* {@link SimpleUrlAuthenticationFailureHandler}
|
* {@link SimpleUrlAuthenticationFailureHandler}
|
||||||
* @param authenticationFailureHandler the {@link AuthenticationFailureHandler} to use
|
* @param authenticationFailureHandler the {@link AuthenticationFailureHandler} to use
|
||||||
* when authentication fails.
|
* when authentication fails.
|
||||||
|
* @deprecated Use {@link #failureHandler(AuthenticationFailureHandler)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.5")
|
||||||
public OneTimeTokenLoginConfigurer<H> authenticationFailureHandler(
|
public OneTimeTokenLoginConfigurer<H> authenticationFailureHandler(
|
||||||
AuthenticationFailureHandler authenticationFailureHandler) {
|
AuthenticationFailureHandler authenticationFailureHandler) {
|
||||||
Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null");
|
Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null");
|
||||||
this.authenticationFailureHandler = authenticationFailureHandler;
|
super.failureHandler(authenticationFailureHandler);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,22 +335,16 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
* {@link SavedRequestAwareAuthenticationSuccessHandler} with no additional properties
|
* {@link SavedRequestAwareAuthenticationSuccessHandler} with no additional properties
|
||||||
* set.
|
* set.
|
||||||
* @param authenticationSuccessHandler the {@link AuthenticationSuccessHandler}.
|
* @param authenticationSuccessHandler the {@link AuthenticationSuccessHandler}.
|
||||||
|
* @deprecated Use {@link #successHandler(AuthenticationSuccessHandler)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.5")
|
||||||
public OneTimeTokenLoginConfigurer<H> authenticationSuccessHandler(
|
public OneTimeTokenLoginConfigurer<H> authenticationSuccessHandler(
|
||||||
AuthenticationSuccessHandler authenticationSuccessHandler) {
|
AuthenticationSuccessHandler authenticationSuccessHandler) {
|
||||||
Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
|
Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
|
||||||
this.authenticationSuccessHandler = authenticationSuccessHandler;
|
super.successHandler(authenticationSuccessHandler);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthenticationFailureHandler getAuthenticationFailureHandler() {
|
|
||||||
if (this.authenticationFailureHandler != null) {
|
|
||||||
return this.authenticationFailureHandler;
|
|
||||||
}
|
|
||||||
this.authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler("/login?error");
|
|
||||||
return this.authenticationFailureHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this {@link GenerateOneTimeTokenRequestResolver} when resolving
|
* Use this {@link GenerateOneTimeTokenRequestResolver} when resolving
|
||||||
* {@link GenerateOneTimeTokenRequest} from {@link HttpServletRequest}. By default,
|
* {@link GenerateOneTimeTokenRequest} from {@link HttpServletRequest}. By default,
|
||||||
|
@ -3039,7 +3039,8 @@ public class ServerHttpSecurity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (http.formLogin != null && http.formLogin.isEntryPointExplicit
|
if (http.formLogin != null && http.formLogin.isEntryPointExplicit
|
||||||
|| http.oauth2Login != null && StringUtils.hasText(http.oauth2Login.loginPage)) {
|
|| http.oauth2Login != null && StringUtils.hasText(http.oauth2Login.loginPage)
|
||||||
|
|| http.oneTimeTokenLogin != null && StringUtils.hasText(http.oneTimeTokenLogin.loginPage)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LoginPageGeneratingWebFilter loginPage = null;
|
LoginPageGeneratingWebFilter loginPage = null;
|
||||||
@ -3054,6 +3055,13 @@ public class ServerHttpSecurity {
|
|||||||
}
|
}
|
||||||
loginPage.setOauth2AuthenticationUrlToClientName(urlToText);
|
loginPage.setOauth2AuthenticationUrlToClientName(urlToText);
|
||||||
}
|
}
|
||||||
|
if (http.oneTimeTokenLogin != null) {
|
||||||
|
if (loginPage == null) {
|
||||||
|
loginPage = new LoginPageGeneratingWebFilter();
|
||||||
|
}
|
||||||
|
loginPage.setOneTimeTokenEnabled(true);
|
||||||
|
loginPage.setGenerateOneTimeTokenUrl(http.oneTimeTokenLogin.tokenGeneratingUrl);
|
||||||
|
}
|
||||||
if (loginPage != null) {
|
if (loginPage != null) {
|
||||||
http.addFilterAt(loginPage, SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING);
|
http.addFilterAt(loginPage, SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING);
|
||||||
http.addFilterBefore(DefaultResourcesWebFilter.css(), SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING);
|
http.addFilterBefore(DefaultResourcesWebFilter.css(), SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING);
|
||||||
@ -5954,11 +5962,13 @@ public class ServerHttpSecurity {
|
|||||||
|
|
||||||
private boolean submitPageEnabled = true;
|
private boolean submitPageEnabled = true;
|
||||||
|
|
||||||
|
private String loginPage;
|
||||||
|
|
||||||
protected void configure(ServerHttpSecurity http) {
|
protected void configure(ServerHttpSecurity http) {
|
||||||
configureSubmitPage(http);
|
configureSubmitPage(http);
|
||||||
configureOttGenerateFilter(http);
|
configureOttGenerateFilter(http);
|
||||||
configureOttAuthenticationFilter(http);
|
configureOttAuthenticationFilter(http);
|
||||||
configureDefaultLoginPage(http);
|
configureDefaultEntryPoint(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureOttAuthenticationFilter(ServerHttpSecurity http) {
|
private void configureOttAuthenticationFilter(ServerHttpSecurity http) {
|
||||||
@ -5995,17 +6005,29 @@ public class ServerHttpSecurity {
|
|||||||
http.addFilterAt(generateFilter, SecurityWebFiltersOrder.ONE_TIME_TOKEN);
|
http.addFilterAt(generateFilter, SecurityWebFiltersOrder.ONE_TIME_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureDefaultLoginPage(ServerHttpSecurity http) {
|
private void configureDefaultEntryPoint(ServerHttpSecurity http) {
|
||||||
if (http.formLogin != null) {
|
MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher(
|
||||||
for (WebFilter webFilter : http.webFilters) {
|
MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML,
|
||||||
OrderedWebFilter orderedWebFilter = (OrderedWebFilter) webFilter;
|
MediaType.TEXT_PLAIN);
|
||||||
if (orderedWebFilter.webFilter instanceof LoginPageGeneratingWebFilter loginPageGeneratingFilter) {
|
htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||||
loginPageGeneratingFilter.setOneTimeTokenEnabled(true);
|
ServerWebExchangeMatcher xhrMatcher = (exchange) -> {
|
||||||
loginPageGeneratingFilter.setGenerateOneTimeTokenUrl(this.tokenGeneratingUrl);
|
if (exchange.getRequest().getHeaders().getOrEmpty("X-Requested-With").contains("XMLHttpRequest")) {
|
||||||
break;
|
return ServerWebExchangeMatcher.MatchResult.match();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return ServerWebExchangeMatcher.MatchResult.notMatch();
|
||||||
|
};
|
||||||
|
ServerWebExchangeMatcher notXhrMatcher = new NegatedServerWebExchangeMatcher(xhrMatcher);
|
||||||
|
ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher(notXhrMatcher,
|
||||||
|
htmlMatcher);
|
||||||
|
String loginPage = "/login";
|
||||||
|
if (this.loginPage != null) {
|
||||||
|
loginPage = this.loginPage;
|
||||||
}
|
}
|
||||||
|
RedirectServerAuthenticationEntryPoint defaultEntryPoint = new RedirectServerAuthenticationEntryPoint(
|
||||||
|
loginPage);
|
||||||
|
defaultEntryPoint.setRequestCache(http.requestCache.requestCache);
|
||||||
|
http.defaultEntryPoints.add(new DelegateEntry(defaultEntryPointMatcher, defaultEntryPoint));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6233,6 +6255,19 @@ public class ServerHttpSecurity {
|
|||||||
return this.tokenGenerationSuccessHandler;
|
return this.tokenGenerationSuccessHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the URL to send users to if login is required. A default login page
|
||||||
|
* will be generated when this attribute is not specified.
|
||||||
|
* @param loginPage the URL to send users to if login is required
|
||||||
|
* @return the {@link OAuth2LoginSpec} for further configuration
|
||||||
|
* @since 6.5
|
||||||
|
*/
|
||||||
|
public OneTimeTokenLoginSpec loginPage(String loginPage) {
|
||||||
|
Assert.hasText(loginPage, "loginPage cannot be empty");
|
||||||
|
this.loginPage = loginPage;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2024 the original author or authors.
|
* Copyright 2002-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -62,12 +62,12 @@ class OneTimeTokenLoginDsl {
|
|||||||
tokenService?.also { oneTimeTokenLoginConfigurer.tokenService(tokenService) }
|
tokenService?.also { oneTimeTokenLoginConfigurer.tokenService(tokenService) }
|
||||||
authenticationConverter?.also { oneTimeTokenLoginConfigurer.authenticationConverter(authenticationConverter) }
|
authenticationConverter?.also { oneTimeTokenLoginConfigurer.authenticationConverter(authenticationConverter) }
|
||||||
authenticationFailureHandler?.also {
|
authenticationFailureHandler?.also {
|
||||||
oneTimeTokenLoginConfigurer.authenticationFailureHandler(
|
oneTimeTokenLoginConfigurer.failureHandler(
|
||||||
authenticationFailureHandler
|
authenticationFailureHandler
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
authenticationSuccessHandler?.also {
|
authenticationSuccessHandler?.also {
|
||||||
oneTimeTokenLoginConfigurer.authenticationSuccessHandler(
|
oneTimeTokenLoginConfigurer.successHandler(
|
||||||
authenticationSuccessHandler
|
authenticationSuccessHandler
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ public class OneTimeTokenLoginConfigurerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void oneTimeTokenWhenFormLoginConfiguredThenRendersRequestTokenForm() throws Exception {
|
void oneTimeTokenWhenConfiguredThenRendersRequestTokenForm() throws Exception {
|
||||||
this.spring.register(OneTimeTokenFormLoginConfig.class).autowire();
|
this.spring.register(OneTimeTokenDefaultConfig.class).autowire();
|
||||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@ -168,21 +168,7 @@ public class OneTimeTokenLoginConfigurerTests {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<form class="login-form" method="post" action="/login">
|
|
||||||
<h2>Please sign in</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<label for="username" class="screenreader">Username</label>
|
|
||||||
<input type="text" id="username" name="username" placeholder="Username" required autofocus>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label for="password" class="screenreader">Password</label>
|
|
||||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<input name="_csrf" type="hidden" value="%s" />
|
|
||||||
<button type="submit" class="primary">Sign in</button>
|
|
||||||
</form>
|
|
||||||
<form id="ott-form" class="login-form" method="post" action="/ott/generate">
|
<form id="ott-form" class="login-form" method="post" action="/ott/generate">
|
||||||
<h2>Request a One-Time Token</h2>
|
<h2>Request a One-Time Token</h2>
|
||||||
|
|
||||||
@ -202,6 +188,14 @@ public class OneTimeTokenLoginConfigurerTests {
|
|||||||
//@formatter:on
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void oneTimeTokenWhenLoginPageConfiguredThenRedirects() throws Exception {
|
||||||
|
this.spring.register(OneTimeTokenLoginPageConfig.class).autowire();
|
||||||
|
this.mvc.perform(get("/login"))
|
||||||
|
.andExpect(status().isFound())
|
||||||
|
.andExpect(redirectedUrl("http://localhost/custom-login"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void oneTimeTokenWhenNoTokenGenerationSuccessHandlerThenException() {
|
void oneTimeTokenWhenNoTokenGenerationSuccessHandlerThenException() {
|
||||||
assertThatException()
|
assertThatException()
|
||||||
@ -304,6 +298,34 @@ public class OneTimeTokenLoginConfigurerTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Import(UserDetailsServiceConfig.class)
|
||||||
|
static class OneTimeTokenLoginPageConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain securityFilterChain(HttpSecurity http,
|
||||||
|
OneTimeTokenGenerationSuccessHandler ottSuccessHandler) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.authorizeHttpRequests((authz) -> authz
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.oneTimeTokenLogin((ott) -> ott
|
||||||
|
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
||||||
|
.loginPage("/custom-login")
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
TestOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
|
||||||
|
return new TestOneTimeTokenGenerationSuccessHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Import(UserDetailsServiceConfig.class)
|
@Import(UserDetailsServiceConfig.class)
|
||||||
@ -321,7 +343,7 @@ public class OneTimeTokenLoginConfigurerTests {
|
|||||||
.tokenGeneratingUrl("/generateurl")
|
.tokenGeneratingUrl("/generateurl")
|
||||||
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
||||||
.loginProcessingUrl("/loginprocessingurl")
|
.loginProcessingUrl("/loginprocessingurl")
|
||||||
.authenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/authenticated"))
|
.successHandler(new SimpleUrlAuthenticationSuccessHandler("/authenticated"))
|
||||||
);
|
);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -334,34 +356,6 @@ public class OneTimeTokenLoginConfigurerTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@EnableWebSecurity
|
|
||||||
@Import(UserDetailsServiceConfig.class)
|
|
||||||
static class OneTimeTokenFormLoginConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
SecurityFilterChain securityFilterChain(HttpSecurity http,
|
|
||||||
OneTimeTokenGenerationSuccessHandler ottSuccessHandler) throws Exception {
|
|
||||||
// @formatter:off
|
|
||||||
http
|
|
||||||
.authorizeHttpRequests((authz) -> authz
|
|
||||||
.anyRequest().authenticated()
|
|
||||||
)
|
|
||||||
.formLogin(Customizer.withDefaults())
|
|
||||||
.oneTimeTokenLogin((ott) -> ott
|
|
||||||
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
|
||||||
);
|
|
||||||
// @formatter:on
|
|
||||||
return http.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
TestOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
|
|
||||||
return new TestOneTimeTokenGenerationSuccessHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Import(UserDetailsServiceConfig.class)
|
@Import(UserDetailsServiceConfig.class)
|
||||||
|
@ -250,6 +250,41 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void oneTimeTokenWhenConfiguredThenRendersRequestTokenForm() {
|
||||||
|
this.spring.register(OneTimeTokenDefaultConfig.class).autowire();
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
byte[] responseByteArray = this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
|
.get()
|
||||||
|
.uri((uriBuilder) -> uriBuilder
|
||||||
|
.path("/login")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.exchange()
|
||||||
|
.expectBody()
|
||||||
|
.returnResult()
|
||||||
|
.getResponseBody();
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
String response = new String(responseByteArray);
|
||||||
|
|
||||||
|
assertThat(response.contains(EXPECTED_HTML_HEAD)).isTrue();
|
||||||
|
assertThat(response.contains(GENERATE_OTT_PART)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void oneTimeTokenWhenConfiguredThenRedirectsToLoginPage() {
|
||||||
|
this.spring.register(OneTimeTokenDefaultConfig.class).autowire();
|
||||||
|
|
||||||
|
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
|
.get()
|
||||||
|
.uri((uriBuilder) -> uriBuilder.path("/").build())
|
||||||
|
.exchange()
|
||||||
|
.expectHeader()
|
||||||
|
.location("/login");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void oneTimeTokenWhenFormLoginConfiguredThenRendersRequestTokenForm() {
|
void oneTimeTokenWhenFormLoginConfiguredThenRendersRequestTokenForm() {
|
||||||
this.spring.register(OneTimeTokenFormLoginConfig.class).autowire();
|
this.spring.register(OneTimeTokenFormLoginConfig.class).autowire();
|
||||||
@ -280,6 +315,18 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
return lastToken;
|
return lastToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void oneTimeTokenWhenCustomLoginPageThenRedirects() {
|
||||||
|
this.spring.register(OneTimeTokenDifferentUrlsConfig.class).autowire();
|
||||||
|
|
||||||
|
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
|
.get()
|
||||||
|
.uri((uriBuilder) -> uriBuilder.path("/login").build())
|
||||||
|
.exchange()
|
||||||
|
.expectHeader()
|
||||||
|
.location("/custom-login");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void oneTimeTokenWhenNoOneTimeTokenGenerationSuccessHandlerThenException() {
|
void oneTimeTokenWhenNoOneTimeTokenGenerationSuccessHandlerThenException() {
|
||||||
assertThatException()
|
assertThatException()
|
||||||
@ -362,6 +409,7 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
.authenticated()
|
.authenticated()
|
||||||
)
|
)
|
||||||
.oneTimeTokenLogin((ott) -> ott
|
.oneTimeTokenLogin((ott) -> ott
|
||||||
|
.loginPage("/custom-login")
|
||||||
.tokenGeneratingUrl("/generateurl")
|
.tokenGeneratingUrl("/generateurl")
|
||||||
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
||||||
.loginProcessingUrl("/loginprocessingurl")
|
.loginProcessingUrl("/loginprocessingurl")
|
||||||
|
@ -42,8 +42,8 @@ In the following sections we will explore how to configure OTT Login for your ne
|
|||||||
[[default-pages]]
|
[[default-pages]]
|
||||||
== Default Login Page and Default One-Time Token Submit Page
|
== Default Login Page and Default One-Time Token Submit Page
|
||||||
|
|
||||||
The `oneTimeTokenLogin()` DSL can be used in conjunction with `formLogin()`, which will produce an additional One-Time Token Request Form in the xref:servlet/authentication/passwords/form.adoc[default generated login page].
|
When the `oneTimeTokenLogin()` DSL is used, by default the One-Time Token Login Page is auto-generated by the org.springframework.security.web.authentication.ui:DefaultLoginPageGeneratingFilter[].
|
||||||
It will also set up the javadoc:org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter[] to generate a default One-Time Token submit page.
|
The DSL will also set up the javadoc:org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter[] to generate a default One-Time Token submit page.
|
||||||
|
|
||||||
[[sending-token-to-user]]
|
[[sending-token-to-user]]
|
||||||
== Sending the Token to the User
|
== Sending the Token to the User
|
||||||
|
@ -43,11 +43,13 @@ import static org.springframework.security.web.util.matcher.AntPathRequestMatche
|
|||||||
*/
|
*/
|
||||||
public final class GenerateOneTimeTokenFilter extends OncePerRequestFilter {
|
public final class GenerateOneTimeTokenFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
public static final String DEFAULT_GENERATE_URL = "/ott/generate";
|
||||||
|
|
||||||
private final OneTimeTokenService tokenService;
|
private final OneTimeTokenService tokenService;
|
||||||
|
|
||||||
private final OneTimeTokenGenerationSuccessHandler tokenGenerationSuccessHandler;
|
private final OneTimeTokenGenerationSuccessHandler tokenGenerationSuccessHandler;
|
||||||
|
|
||||||
private RequestMatcher requestMatcher = antMatcher(HttpMethod.POST, "/ott/generate");
|
private RequestMatcher requestMatcher = antMatcher(HttpMethod.POST, DEFAULT_GENERATE_URL);
|
||||||
|
|
||||||
private GenerateOneTimeTokenRequestResolver requestResolver = new DefaultGenerateOneTimeTokenRequestResolver();
|
private GenerateOneTimeTokenRequestResolver requestResolver = new DefaultGenerateOneTimeTokenRequestResolver();
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2024 the original author or authors.
|
* Copyright 2002-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -133,7 +133,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return this.formLoginEnabled || this.oauth2LoginEnabled || this.saml2LoginEnabled;
|
return this.formLoginEnabled || this.oauth2LoginEnabled || this.saml2LoginEnabled || this.oneTimeTokenEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLogoutSuccessUrl(String logoutSuccessUrl) {
|
public void setLogoutSuccessUrl(String logoutSuccessUrl) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2024 the original author or authors.
|
* Copyright 2002-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -28,6 +28,7 @@ import jakarta.servlet.ServletException;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationFilter;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -43,11 +44,13 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
|||||||
*/
|
*/
|
||||||
public final class DefaultOneTimeTokenSubmitPageGeneratingFilter extends OncePerRequestFilter {
|
public final class DefaultOneTimeTokenSubmitPageGeneratingFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
private RequestMatcher requestMatcher = new AntPathRequestMatcher("/login/ott", "GET");
|
public static final String DEFAULT_SUBMIT_PAGE_URL = "/login/ott";
|
||||||
|
|
||||||
|
private RequestMatcher requestMatcher = new AntPathRequestMatcher(DEFAULT_SUBMIT_PAGE_URL, "GET");
|
||||||
|
|
||||||
private Function<HttpServletRequest, Map<String, String>> resolveHiddenInputs = (request) -> Collections.emptyMap();
|
private Function<HttpServletRequest, Map<String, String>> resolveHiddenInputs = (request) -> Collections.emptyMap();
|
||||||
|
|
||||||
private String loginProcessingUrl = "/login/ott";
|
private String loginProcessingUrl = OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user