Spring Security: Convert in-memory auth to database - java

I'm using in-memory auth to have my login working in spring
However, I want to change it now to persistent database
Please see code below:
JWTWebSecurityConfig
package com.sbc.cpex.security.jwt;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class JWTWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtUnAuthorizedResponseAuthenticationEntryPoint jwtUnAuthorizedResponseAuthenticationEntryPoint;
#Autowired
private UserDetailsService jwtInMemoryUserDetailsService;
#Autowired
private JwtTokenAuthorizationOncePerRequestFilter jwtAuthenticationTokenFilter;
#Value("${jwt.get.token.uri}")
private String authenticationPath;
#Autowired
DataSource dataSource;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth
// .userDetailsService(jwtInMemoryUserDetailsService)
// .passwordEncoder(passwordEncoderBean());
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username, password"
+ " from users where username=?")
.passwordEncoder(passwordEncoderBean());
}
#Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
// .csrf().and().cors().disable()
.exceptionHandling().authenticationEntryPoint(jwtUnAuthorizedResponseAuthenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.anyRequest().authenticated();
httpSecurity
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
httpSecurity
.headers()
.frameOptions().sameOrigin() //H2 Console Needs this setting
.cacheControl(); //disable caching
}
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
.antMatchers(HttpMethod.OPTIONS, "/**")
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/" //Other Stuff You want to Ignore
)
.and()
.ignoring()
.antMatchers("/h2-console/**/**");//Should not be in Production!
}
}
Steps I did:
1. Comment out these lines
auth
.userDetailsService(jwtInMemoryUserDetailsService)
.passwordEncoder(passwordEncoderBean());
Add the following lines for jdbcauth
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username, password"
+ " from users where username=?")
.passwordEncoder(passwordEncoderBean());
Create a class called DataSourceConfig
package com.sbc.cpex.security.jwt;
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class DataSourceConfig {
#Bean
public DataSource getDataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.username("test");
dataSourceBuilder.password("pass");
return dataSourceBuilder.build();
}
}
But I'm getting this error
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'h2Console' defined in class path resource [org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.ServletRegistrationBean]: Factory method 'h2Console' threw exception; nested exception is java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
Please enlighten me. TIA

The stack trace itself is self explanatory :
nested exception is java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
You need to provide the Datasource url when creating a bean of Datasource.
From the stacktrace I could understand that you are using H2 . So, you could create a bean like :
#Bean
public DataSource getDataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("org.h2.Driver");
dataSourceBuilder.url("jdbc:h2:mem:test");
dataSourceBuilder.username("username");
dataSourceBuilder.password("");
return dataSourceBuilder.build();
}
In your code, you only provided the username and password part, hence it is throwing the error.
#iamjpcbau Springboot is autoconfiguring H2 as the databse as it is found as a dependency during class path scanning. Since you have provided a Datasource bean , spring automatically takes it up for configuring H2 but the url is missing , which causes the exception that you are receiving.
Inorder to configure another database with your project, configure the database through application.properties or application.yml or manually create configuration beans so that the configuration for your corresponding database is taken up at startup instead of H2.Now, since there are no other database configured and since H2 is found on classpath , spring is configuring that by default.

Related

Spring Boot WebSecurityConfigurerAdapter does not exists

I am new in spring boot, and I am trying to work with JWT.
I follwed many examples and all looks the same.
Before,15 days I make classic auth application with JWT and all works fine, but now I am facing some errors there.
https://github.com/nedim-bajric/basicJWTspring this is a repo of project that I was created before 15 days and it works fine.
Error I gets comming from SecurityConfiguration and it says that is not possible to find WebSecurityConfigurerAdapter, and it is not possilbe to #Overide configure method.
Also, there is problem with .antMatchers, it says Cannot resolve method 'antMatchers' in 'ExpressionInterceptUrlRegistry'.
There is my config file
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.unze.sis.security.jwt.AuthEntryPointJwt;
import com.unze.sis.security.jwt.AuthTokenFilter;
import com.unze.sis.security.services.UserDetailsServiceImpl;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
// securedEnabled = true,
// jsr250Enabled = true,
prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsServiceImpl userDetailsService;
#Autowired
private AuthEntryPointJwt unauthorizedHandler;
#Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
I tried few solutions that I found on stackowerflow, but it doesn't work.

type org.springframework.security.authentication.encoding.PasswordEncoder cannot be resolved. It is indirectly referenced from required .class files

Hi there so I'm trying to create a Spring Security Login page which roots back to my DB(sql server) where my credentials are stored.
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
//Some imports like JDBC template and beanrowmapper are present but dont mind them.. as i was trying somethings out..
#Configuration
#EnableWebSecurity
public class SecurityConfigWithDB extends WebSecurityConfigurerAdapter{
#Autowired
private DataSource dataSource;
#Bean
public PasswordEncoder passwordEncoder1() {
return new BCryptPasswordEncoder();
}
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.passwordEncoder(new BCryptPasswordEncoder()) // this is where i get the error//
.dataSource(dataSource)
.usersByUsernameQuery("Select UserName, Password, Enable FROM LoginDetails WHERE Username=?")
.authoritiesByUsernameQuery("Select UserName, Role FROM LoginDetails WHERE Username=?");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.logout().permitAll();
}
}
And the error goes like :
The type org.springframework.security.authentication.encoding.PasswordEncoder cannot be resolved. It is indirectly referenced from required .class files

Spring Boot Security - Postman gives 401 Unauthorized

I am developing rest APIs in Spring Boot. I am able to do CRUD operations and postman gives correct responses, but when I add Spring Security username and password Postman gives 401 Unauthorized.
I have provided a spring boot security username and password as below.
application.proptries
spring.jpa.hibernate.ddl-auto=update
spring.datasource.platform=mysql
spring.datasource.url=jdbc:mysql://localhost:3306/pal?createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.security.user.name=root
spring.security.user.password=root
I have done basic auth with username as root and password as root.
Preview request gives headers updated successfully message :
EDIT
I have deleted the cookies in postman but still facing the same issue
SecurityConfing.java
My Security Configuration are as below.
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
#Order(1000)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
authenticationMgr.jdbcAuthentication().dataSource(dataSource())
.usersByUsernameQuery(
"select email,password from user where email=? and statusenable=true")
.authoritiesByUsernameQuery(
"select email,role from user where email=? and statusenable=true");
System.out.println(authenticationMgr.jdbcAuthentication().dataSource(dataSource())
.usersByUsernameQuery(
"select email,password from user where email=? and statusenable=true")
.authoritiesByUsernameQuery(
"select email,role from user where email=? and statusenable=true"));
}
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/pal");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("");
return driverManagerDataSource;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests().antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.authorizeRequests().antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER").anyRequest().permitAll()
.and()
.authorizeRequests().antMatchers("/user/**").hasAnyRole("ROLE_USER").anyRequest().permitAll();
}
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST,"/newuser").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.POST,"/newuser/*").permitAll()
.antMatchers(HttpMethod.GET,"/master/*").permitAll()
.antMatchers(HttpMethod.GET,"/exploreCourse").permitAll()
.anyRequest().authenticated()
}
}
You need to configure Spring Security, by default all routes all secured for authrorization.
Please have a look JWT Token implementation at this Link.
If Authorization needed in spring boot, the below annotation at root configuration class.
#EnableAuthorizationServer
( and other required annotations)
public class Application{
....
....
}
Below dependency also needed to be added
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>

How to enable #Secured annotation in spring application

I'm using sprig security 4.0.4.RELEASE in my Spring 4.2.5.RELEASE application.
I want to implement the role wise security on method level in my application using #Secured annotation
I'm tried to implement this by adding #EnableGlobalMethodSecurity(securedEnabled = true) but some error is occurring.
Here is my SecurityConfiguration Class
package com.application.security;
import com.application.security.LoginSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;
#Autowired
LoginSuccessHandler loginSuccessHandler;
#Autowired
PersistentTokenRepository tokenRepository;
/*#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}*/
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(customDaoAuthenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().invalidSessionUrl("/logout");
http.authorizeRequests()
/*.antMatchers("/").access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")*/
.antMatchers("/registration").permitAll()
.antMatchers("/exclusion").permitAll()
.antMatchers("/landing").permitAll()
.antMatchers("/uploadSingle").permitAll()
.antMatchers("/uploadSingleNoFile").permitAll()
.antMatchers("/loadHtmlTableAjax").permitAll()
.antMatchers("/AllclaimDetails").permitAll()
.antMatchers("/deleteclaim").permitAll()
.antMatchers("/claimComplete").permitAll()
.antMatchers("/exclusionComplete").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.loginProcessingUrl("/login").usernameParameter("username").passwordParameter("password")
.successHandler(loginSuccessHandler)
.failureUrl("/login?error=true")
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
.permitAll()
.and()
.rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository).tokenValiditySeconds(86400)
.and()
.csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**","/logoff");
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Bean
CustomDaoAuthenticationProvider customDaoAuthenticationProvider() {
CustomDaoAuthenticationProvider customAuthenticationProvider = new CustomDaoAuthenticationProvider();
customAuthenticationProvider.setUserDetailsService(userDetailsService);
customAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return customAuthenticationProvider;
}
#Bean
public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
PersistentTokenBasedRememberMeServices tokenBasedservice = new PersistentTokenBasedRememberMeServices(
"remember-me", userDetailsService, tokenRepository);
return tokenBasedservice;
}
#Bean
public AuthenticationTrustResolver getAuthenticationTrustResolver() {
return new AuthenticationTrustResolverImpl();
}
}
When I'm giving #EnableGlobalMethodSecurity(securedEnabled = true) , the application is not getting started. I'm getting the below error.
The problem is from AuthenticationTrustResolver bean
AnnotationConfigWebApplicationContext:546 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appConfig': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'metaDataSourceAdvisor': Cannot resolve reference to bean 'methodSecurityMetadataSource' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration.setAuthenticationTrustResolver(org.springframework.security.authentication.AuthenticationTrustResolver); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setTrustResolver(org.springframework.security.authentication.AuthenticationTrustResolver); nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'getAuthenticationTrustResolver': Requested bean is currently in creation: Is there an unresolvable circular reference?
Can somebody tell me the reason?
Please create Initializer class by extending AbstractSecurityWebApplicationInitializer.
Please refer my answer in here.
No bean named 'springSecurityFilterChain' available
I solved this problem by updating my spring security dependency to latest in pom.xml
I changed the version from
<springsecurity.version>4.0.4.RELEASE</springsecurity.version>
to
<springsecurity.version>4.2.3.RELEASE</springsecurity.version>

AuthenticationSuccessHandler in Spring Security

I've used spring security in a Spring Boot application and there are 2 types of users: one is an ADMIN, and one just a simple user. I get the data from a DataSource, then I execute an SQL query.
My problem is with a redirection: for every user I have a different homepage. I'm trying to use to AthenticationSuccessHandler, but it won't work.
Please help.
My Spring security class configuration :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import javax.sql.DataSource;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
Securityhandler successHandler;
// Pour l'authentification des Utilisateur de Table Utilisateur
#Autowired
public void GlobalConfig(AuthenticationManagerBuilder auth,DataSource dataSource) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT \"Pseudo\" AS principal , \"Password\" AS credentials , true FROM \"UTILISATEUR\" WHERE \"Pseudo\" = ? ")
.authoritiesByUsernameQuery("SELECT u.\"Pseudo\" AS principal , r.role as role FROM \"UTILISATEUR\" u ,\"Role\" r where u.id_role=r.id_role AND \"Pseudo\" = ? ")
.rolePrefix("_ROLE");
}
// ne pas appliqué la securité sur les ressources
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/bootstrap/**","/css/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(successHandler);
}
}
And this is my AuthenticationSuccessHandler:
import java.io.IOException;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
public class Securityhandler implements AuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
if (roles.contains("ROLE_Admin")) {
response.sendRedirect("/admin/home.html");
}
}
}
And this is the error in the console:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name
'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration':
Injection of autowired dependencies failed;
import java.io.IOException;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
#Component
public class Securityhandler implements AuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
if (roles.contains("ROLE_ADMIN")) {
response.sendRedirect("admin/home.html");
}
}
}
You've missed the #Component annotation in your success handler class.
Rather than sublcassing AuthenticationSuccessHandler,
It's worth knowing about the Spring security role-checking config:
#Configuration
#EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN");
}
...
}
OR pre-checking a Role per endpoint:
#Autowired
#PreAuthorize("hasRole('ADMIN')")
#RequestMapping("/")
public ModelAndView home(HttpServletRequest request) throws Exception {
}
where the default Role prefix is ROLE_
https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html
https://www.baeldung.com/spring-security-expressions-basic

Categories