Spring Security Keycloak Adapter cannot handle single sign-out when logout from another tab in browser - spring-boot

I have implemented a spring boot web app using spring security and Keycloak to authenticate users based on this tutorial. I used maven, spring boot 2.2.2 and Keycloak 8.0.1. All things works correctly except a problem in single sign-out. When I open the secured path of spring boot app in a tab of my browser (http://localhost:8080/books) and Keycloak account page (http://localhost:8180/auth/realms/{realm_name}/account) in another tab and login with one of the users in one of them, the other tab will aware of the login and after reload the page, that page will also be authenticated. But the problem is where, when both tabs are logged in and first I log out from account page, and reload spring boot app, the user remains active and the app does not aware of the log out action in other tabs. How can I handle this problem?
my project resource tree is like image below:
Project resource tree
This is my pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sso</groupId>
<artifactId>demoapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demoapp</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>13</java.version>
<keycloak.version>8.0.1</keycloak.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- Keycloak Adapter -->
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-test-helper</artifactId>
<version>${keycloak.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>${keycloak.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
This is SecurityConfig.java :
#KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
grantedAuthorityMapper.setPrefix("ROLE_");
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
auth.authenticationProvider(keycloakAuthenticationProvider);
}
/**
* Defines the session authentication strategy.
*/
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
/**
* Define an HttpSessionManager bean only if missing.
*/
#Bean
#Override
#ConditionalOnMissingBean(HttpSessionManager.class)
protected HttpSessionManager httpSessionManager() {
return new HttpSessionManager();
}
/**
* Define security constraints for the application resources.
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers("/books").authenticated()
.antMatchers("/manager").hasRole("admin")
.anyRequest().permitAll();
}
#Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
}
This is LibraryController.java :
#Controller
public class LibraryController {
private final HttpServletRequest request;
private final BookRepository bookRepository;
#Autowired
public LibraryController(HttpServletRequest request, BookRepository bookRepository) {
this.request = request;
this.bookRepository = bookRepository;
}
#GetMapping(value = "/")
public String getHome() {
return "index";
}
#GetMapping(value = "/books")
public String getBooks(Model model) {
configCommonAttributes(model);
model.addAttribute("books", bookRepository.readAll());
return "books";
}
#GetMapping(value = "/manager")
public String getManager(Model model) {
configCommonAttributes(model);
model.addAttribute("books", bookRepository.readAll());
return "manager";
}
#GetMapping(value = "/logout")
public String logout() throws ServletException {
request.logout();
return "redirect:/";
}
private void configCommonAttributes(Model model) {
model.addAttribute("firstname", getKeycloakSecurityContext().getIdToken().getGivenName());
model.addAttribute("lastname", getKeycloakSecurityContext().getIdToken().getFamilyName());
model.addAttribute("email", getKeycloakSecurityContext().getIdToken().getEmail());
}
/**
* The KeycloakSecurityContext provides access to several pieces of information
* contained in the security token, such as user profile information.
*/
private KeycloakSecurityContext getKeycloakSecurityContext() {
return (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
}
}
and below is my DemoappApplication.java :
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoappApplication {
public static void main(String[] args) {
SpringApplication.run(DemoappApplication.class, args);
}
}

The problem was just solved by setting the base URL of my spring boot application as Admin-URL in the corresponding client configuration page of Keycloak server (admin console). Now, the spring boot app is aware of user log out from other apps.

Related

Why is my security filter chain not working?

I want to permit access to all of my pages and put authentication each page at a time, but I can't even permit access to all my pages. My SecurityConfig is as below (I got this peace of code at spring.io):
#Configuration
public class SecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz
.requestMatchers("/*").permitAll()
);
return http.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Once I try to access any endpoint, I get a login screen:
I can't get it to work. Why is it asking authentication to all endpoints of my application? Shouldn't this be enough to permit access to everything?
package com.servicestcg.servicestcg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import com.servicestcg.servicestcg.controller.CartasController;
#SpringBootApplication
#ComponentScan(basePackageClasses = CartasController.class)
public class ServicesTcgApplication {
public static void main(String[] args) {
SpringApplication.run(ServicesTcgApplication.class, args);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.services-tcg</groupId>
<artifactId>services-tcg</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>services-tcg</name>
<description>Services for tcg website</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
With Spring Security, the sigle "all" is exprimed with "**".
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorization -> authorization
.requestMatchers("/**").permitAll()
);
return http.build();
}
You may encounter another problem with
#SpringBootApplication
#ComponentScan(basePackageClasses = CartasController.class)
public class ServicesTcgApplication {
public static void main(String[] args) {
SpringApplication.run(ServicesTcgApplication.class, args);
}
}
Unless you know what you're doing, you should let spring handle the package scanning for you.
#SpringBootApplication
public class ServicesTcgApplication {
public static void main(String[] args) {
SpringApplication.run(ServicesTcgApplication.class, args);
}
}
More information on Spring Security on https://docs.spring.io/spring-security/reference/index.html

spring boot 2 authorization server - all endpoints return 404

I have an application with an authorization server (OAuth2) which I migrated from Spring Boot 1.X to 2.X. Whenever I try to access any of the endpoint functions (e.g. /oauth/token or /oauth/token_key) it results in HTTP-404. The service itself is up which I can see in /actuator/health. It was working without problems with the old Spring Boot.
I already tried to enable all services but without success. I'm using Spring Boot 2, Resilience4J, and OAuth2.
This is my code:
AuthApplication
#SpringBootApplication
#EnableFeignClients
#EnableCircuitBreaker
#EnableAutoConfiguration
public class AuthApplication {
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
AuthServerConfig
#Configuration
#EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
private CustomUserDetailsService userDetailsService;
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new InMemoryAuthorizationCodeServices();
}
#Bean
public OAuth2AccessDeniedHandler oauthAccessDeniedHandler() {
return new OAuth2AccessDeniedHandler();
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authorizationCodeServices(authorizationCodeServices())
.authenticationManager(this.authenticationManager)
.tokenStore(this.tokenStore())
.userDetailsService(this.userDetailsService)
.approvalStoreDisabled();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme").secret("acme")
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("openid", "request", "write", "read");
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("permitAll()");
}
}
SecurityConfiguration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
private CustomUserDetailsService userDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.anonymous()
.and()
.authorizeRequests()
.anyRequest().permitAll()
.and().logout().permitAll().logoutSuccessUrl("/")
.and().httpBasic().disable().csrf().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(this.passwordEncoder());
}
protected PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
I also added this to the bootstrap.yml in the hope it would help, but it didn't:
management:
endpoints:
web:
exposure:
include: "*"
Why are non of the endpoints of the authorization server available?
EDIT 1
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.domain</groupId>
<artifactId>auth</artifactId>
<version>0.0.2-SNAPSHOT</version>
<name>auth</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
<docker.image.prefix>app</docker.image.prefix>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>

Spring Boot Security with Jdbc Annotation

WebSecurityConfig.java
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/css/**", "/icons/**", "/js/**", "/images/**").permitAll();
http.authorizeRequests().antMatchers("/bootstrap/**", "/icons/**", "/datatables/**", "/jquery/**",
"/font-awesome/**", "/select2/**").permitAll();
http.authorizeRequests().antMatchers("/", "/")
.permitAll()
.anyRequest()
.authenticated()
.and().formLogin()
.loginPage("/userForm")
.usernameParameter("userName").passwordParameter("password")
.defaultSuccessUrl("/login")
.failureUrl("/userForm")
.permitAll().and()
.logout().logoutUrl("/logout")
.logoutSuccessUrl("/logout").permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select username, password, active_status from bgtool_test_users where username = ? and active_status = 'Y'")
.authoritiesByUsernameQuery(
"select username, role from bgtool_test_users where username = ?")
.passwordEncoder(passwordEncoder())
;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
UserController.java
#Controller
public class UserController {
private final Logger logger = LoggerFactory.getLogger(UserController.class);
#Autowired
private GameFacade gameFacade;
#RequestMapping("/userList")
public String list(Model model) {
List<User> users = gameFacade.findAllUsers();
model.addAttribute("users", users);
logger.debug("Users: {}", users);
return "userList";
}
#RequestMapping(value = "/userForm", method = RequestMethod.GET)
public String userForm(Model model) {
User entry = new User();
model.addAttribute("userLogin", entry);
logger.debug("Login Form");
return "loginForm";
}
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(#Valid #ModelAttribute("userLogin") User entry, BindingResult result, Model model) {
System.out.println("setting status N");
if (result.hasErrors()) {
logger.debug("Login Form validation error");
return "loginForm";
} else {
entry = gameFacade.findUserByName(entry.getUserName(), entry.getPassword());
if (entry == null) {
result.rejectValue("password", "error.userLogin", "Username or Password incorrect !!");
return "loginForm";
}
logger.debug("Login Successful", entry);
return "home";
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>frau</groupId>
<artifactId>bgtweb</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<derby.version>10.12.1.1</derby.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${commons-dbcp.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby.version}</version>
<scope>runtime</scope>
</dependency>
<!-- SPRING SECURITY -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jheinzel.maven</groupId>
<artifactId>derby-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<derbyHome>${project.basedir}/data</derbyHome>
<port>1527</port>
<database>EMDb</database>
</configuration>
</plugin>
</plugins>
</build>
</project>
When i try to login, i am redirected back to loginform page. The controller method for mapping "/login" is not getting called as i am not getting my logger messages of same method in the console.
I have checked the SQL queries.they are correct.I am unable to find what is missing.
Any help is appreciated. Thanks in Advance
Your login page url and default success url is the same:
.loginPage("/userForm").usernameParameter("userName").passwordParameter("password")
.defaultSuccessUrl("/userForm")
Do you understand logical chain of Spring Security? You declare pages for each authentication step, configure authentication provider that check you username and and password. it's it. So there are two possible places for error - your mapping (pages and controller) and your DB (jdbcAuthentication()).
You event don't need a controller - only pages and and security config. try to simplify your example and remove controller and debug jdbc authentication
This example show correct way of configuration

When Spring boot project war deployed in tomcat 8 server not working for serving images

Web config for static resources
#Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/**").addResourceLocations("file:///C:/test/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Project pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>project</name>
<description>test.</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<jersey.version>2.7</jersey.version>
<guava.version>18.0</guava.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Dependencies for GuavaCacheManager -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- Dependencies for Unit Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Application configuration
#Configuration
#SpringBootApplication
#EnableTransactionManagement
#EnableCaching
#EnableAsync
#EnableAutoConfiguration
#EnableScheduling
#ComponentScan
public class Application {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* Entry point for the application.
*
* #param args
* Command line arguments.
* #throws Exception
* Thrown when an unexpected Exception is thrown from the
* application.
*/
public static void main(final String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
/**
* Create a CacheManager implementation class to be used by Spring where
*
<code>#Cacheable</code> annotations are applied.
*
* #return A CacheManager instance.
*/
#Bean
public CacheManager cacheManager() {
final GuavaCacheManager cacheManager = new GuavaCacheManager("greetings");
return cacheManager;
}
/**
* Supplies a PasswordEncoder instance to the Spring ApplicationContext. The
* PasswordEncoder is used by the AuthenticationProvider to perform one-way
* hash operations on passwords for credential comparison.
*
* #return A PasswordEncoder.
*/
#Bean
public PasswordEncoder passwordEncoder() {
this.logger.info("passwordEncoder");
return new BCryptPasswordEncoder();
}
public #Bean MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(new MongoClient("127.0.0.1"), "test");
return mongoTemplate;
}
}
In eclipse if I start spring boot application, then application serving images for this url
http://localhost:8080///////images//profile//APM1184//originalImage_7a7zke527_.jpeg
If I deploy war file of this project in local tomcat 8 and start. This URL is not working saying 404 not found.
I have posted my code. please correct me where I went wrong.
Having hard coded resource locations and mongo hosts is going to make it hard for you to manage your application. I would recommend moving those values into a configuration file. At the same time I would recommend using relative or root directory locations for resources instead of having the C:\ in the path as that won't work for deployments to Linux or other environments where the resource isn't on the C:\. My guess is that Tomcat isn't allowing the application to read from that external location due to some security constraints on the Tomcat installation.
I would recommend reading this Getting Started Guide on serving static content: https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot

Where I should place the jsp files in a spring-boot project

Recently, I start to work with the spring-boot, and I am trying convert my old spring projects, all of them being web applications, to use this. I manage to compile, package and run the application, but when I try access them in the browser, I can't reach out my views.
First, I try put the jsp pages in the usual folder src/main/webapp/WEB-INF/jsp, but after read this article from official documentation:
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content
I try put them in the folder src/main/resources. None of this works. Anyone can tell me where I should put this files to allow them be acessible when the application is running?
My pom.xml is this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.spring</groupId>
<artifactId>app</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<start-class>com.spring.app.Application</start-class>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I have this controller to map the views:
#Controller
public class AcessoController {
#RequestMapping(value = "/signin")
public String signin(Model model) {
return "acesso/signin";
}
#RequestMapping(value = "/admin")
public String admin(Model model) {
return "private/admin";
}
#RequestMapping(value = "/index")
public String index(Model model) {
return "public/index";
}
}
and this configuration classes:
WebAppConfig.java
#EnableWebMvc
#Configuration
#ComponentScan(value="com.spring.app")
public class WebAppConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebAppInitializer.java
#Order(value=1)
public class WebAppInitializer implements WebApplicationInitializer {
#SuppressWarnings("resource")
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(WebAppConfig.class);
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext jspContext = new AnnotationConfigWebApplicationContext();
jspContext.register(DispatcherConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(jspContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
DispatcherConfig.java
#Configuration
#Import(WebAppConfig.class)
public class DispatcherConfig {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
If using Jetty or Tomcat as embedded servlet container just change your packaging from jar to war, and launch it with java -jar ...

Resources