Issue
I've setup a simple Spring Security app and enabled web security but can't go to the default login page, it keeps raising Error 404. How to resolve this?
Here're my configurations.
application.properties
# database configs
spring.datasource.url=jdbc:h2:file:./testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
# Create Schema automatically
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
spring.sql.init.mode=always
# Enabling H2 Console
spring.h2.console.enabled=true
# Custom H2 Console URL
spring.h2.console.path=/h2-console
##################################################
# session configs
spring.session.store-type=jdbc
spring.session.jdbc.table-name=SPRING_SESSION
spring.session.jdbc.initialize-schema=always
spring.session.timeout=86400
##################################################
debug=true
##################################################
# user configs
spring.security.user.name=user
spring.security.user.password=password
SecurityConfiguration.java
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final IUserService userService;
@Autowired
public SecurityConfiguration(IUserService userService) {
this.userService = userService;
}
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
authProvider.setPasswordEncoder(getPasswordEncoder());
return authProvider;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth.authenticationProvider(authProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/h2-console/**").permitAll()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll().logoutSuccessUrl("/")
.and().csrf().ignoringAntMatchers("/h2-console/**") // needed to access the h2-console after introducing security module;
.and().headers().frameOptions().sameOrigin() // needed to access the h2-console after introducing security module
.and().logout().invalidateHttpSession(true).deleteCookies("JSESSIONID").logoutSuccessUrl("/login");
}
}
Any help what's going wrong is very much appreciated.
EDIT
[nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : GET "/login", parameters={}
[nio-8080-exec-2] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
[nio-8080-exec-2] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
[nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND
[nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}
[nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
[nio-8080-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
[nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404
EDIT 2
plugins {
id 'org.springframework.boot' version '2.6.1'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.dsam'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.session:spring-session-core'
implementation 'org.springframework.session:spring-session-jdbc'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation' // added manually
implementation 'com.h2database:h2' // added manually
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
test {
useJUnitPlatform()
}
Solution
spring-security auto-configures a /login
page ("view and controller"), but if we want it to work/serve, we must not:
.loginPage(...)
..otherwise we are in charge (to present the view).
From (excellent) javadoc :
loginPage:
Specifies the URL to send users to if login is required. If used with WebSecurityConfigurerAdapter a default login page will be generated when this attribute is not specified. ...
Answered By - xerx593