Skip to content

Commit

Permalink
Update formLogin() sample
Browse files Browse the repository at this point in the history
  • Loading branch information
jgrandja committed Jun 6, 2024
1 parent 0c05d65 commit e32b6af
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 17 deletions.
1 change: 1 addition & 0 deletions samples/form-login/samples-form-login.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
implementation "org.springframework.boot:spring-boot-starter-web"
implementation "org.springframework.boot:spring-boot-starter-security"
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation project(':spring-security-config-feature')

testImplementation "org.springframework.boot:spring-boot-starter-test"
testImplementation "org.springframework.security:spring-security-test"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package sample;

import org.springframework.boot.SpringApplication;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2002-2024 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 sample.config;

import java.util.Arrays;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.feature.DefaultFeatureCatalog;
import org.springframework.security.config.feature.FeatureCatalog;
import org.springframework.security.config.feature.Features;
import org.springframework.security.config.feature.configure.CsrfExploitProtectionFeatureConfigurer;
import org.springframework.security.config.feature.configure.FeatureConfigurer;
import org.springframework.security.config.feature.configure.FormAuthenticationFeatureConfigurer;
import org.springframework.security.config.feature.configure.UrlAuthorizationFeatureConfigurer;
import org.springframework.security.config.feature.model.CsrfExploitProtectionFeature;
import org.springframework.security.config.feature.model.FormAuthenticationFeature;
import org.springframework.security.config.feature.model.UrlAuthorizationFeature;

@Configuration(proxyBeanMethods = false)
public class FeatureConfiguration {

@Bean
public FeatureCatalog featureCatalog() {
DefaultFeatureCatalog featureCatalog = new DefaultFeatureCatalog();
featureCatalog.register(FormAuthenticationFeature.builder().build());
featureCatalog.register(UrlAuthorizationFeature.builder().build());
featureCatalog.register(CsrfExploitProtectionFeature.builder().build());
return featureCatalog;
}

@Bean
public List<FeatureConfigurer> featureConfigurers() {
return Arrays.asList(
new FormAuthenticationFeatureConfigurer(),
new UrlAuthorizationFeatureConfigurer(),
new CsrfExploitProtectionFeatureConfigurer());
}

@Bean
public Features features(FeatureCatalog featureCatalog) {
// @formatter:off
return Features.using(featureCatalog)
.customize(FormAuthenticationFeature.Builder.class,
(builder) -> builder
.loginPage("/login")
.defaultSuccessUrl("/index")
.defaultSuccessUrlAlwaysUse(true)
.failureUrl("/login-error")
)
.customize(UrlAuthorizationFeature.Builder.class,
(builder) -> builder
.allowed(List.of("/assets/**", "/login", "/login-error"))
)
.add(CsrfExploitProtectionFeature.class);
// @formatter:on
}

}
42 changes: 25 additions & 17 deletions samples/form-login/src/main/java/sample/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
Expand All @@ -16,47 +16,55 @@

package sample.config;

import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.feature.Features;
import org.springframework.security.config.feature.configure.Configurable;
import org.springframework.security.config.feature.configure.DefaultFeatureConfigurationContext;
import org.springframework.security.config.feature.configure.FeatureConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@Import(FeatureConfiguration.class)
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class SecurityConfig {

// @formatter:off
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers("/assets/**", "/login", "/login-error").permitAll()
.anyRequest().authenticated()
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,
Features features, List<FeatureConfigurer> featureConfigurers) throws Exception {

Configurable<HttpSecurity> configurable = () -> httpSecurity;

features.toList().forEach((feature) ->
featureConfigurers.forEach((featureConfigurer) ->
featureConfigurer.configure(
new DefaultFeatureConfigurationContext(feature, configurable)
)
.formLogin((formLogin) -> formLogin
.loginPage("/login")
.defaultSuccessUrl("/index", true)
.failureUrl("/login-error")
);
return http.build();
)
);

return httpSecurity.build();
}
// @formatter:on

// @formatter:off
@Bean
public UserDetailsService userDetailsService() {
// @formatter:off
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
// @formatter:on
return new InMemoryUserDetailsManager(user);
}
// @formatter:on

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package sample.web;

import org.springframework.stereotype.Controller;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package sample.web;

import org.springframework.stereotype.Controller;
Expand Down

0 comments on commit e32b6af

Please sign in to comment.