I'm facing a serious problem and I can't figure out how to solve it.
Basically, in my Custom Authentication provider, I can't autowire my customUserDetailsService, it is returning a null pointer exception.
I'm gonna paste all the classes I'm using plus the exception, the problem here is that it autowires but it returns NULL, it doesn't give me an error on the autowiring itself.
SecurityConfig class:
package esercizio.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DbAuthenticationProvider dbAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// SecurityContextHolder.getContext().getAuthentication();
auth.authenticationProvider(new DbAuthenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// .addFilterBefore(
// new HeaderUsernamePasswordAuthenticationFilter(authenticationManager()),
// BasicAuthenticationFilter.class)
.csrf().disable().authorizeRequests().antMatchers("/resources/**").permitAll().antMatchers("/auth/**")
.hasRole("USER").anyRequest().authenticated().and().formLogin()
// .loginPage("/login.jsp")
.loginProcessingUrl("/signin").permitAll().failureForwardUrl("/errorPage")
.successForwardUrl("/successPage").and().logout().addLogoutHandler(customLogoutHandler())
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
// .and()
// .exceptionHandling().accessDeniedPage("/403");
}
@Bean
public CustomLogoutHandler customLogoutHandler() {
return new CustomLogoutHandler();
}
}
Custom Authentication Provider:
package esercizio.security;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
@Component
public class DbAuthenticationProvider implements AuthenticationProvider {
Logger logger = LogManager.getLogger(this.getClass());
@Autowired
UserDetailsService customUserDetailsService;
public DbAuthenticationProvider() {
// TODO Auto-generated constructor stub
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String name = authentication.getName();
Object credentials = authentication.getCredentials();
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
UserDetails user = customUserDetailsService.loadUserByUsername(name);
Authentication auth = null;
if (!(credentials instanceof String)) {
return null;
}
String password = null;
try {
password = getMD5(credentials.toString());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (user != null && (user.getUsername().equals(name) && user.getPassword().equals(password))) {
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
auth = new UsernamePasswordAuthenticationToken(name, password, grantedAuthorities);
} else {
throw new BadCredentialsException("Errore nell'autenticazione");
}
return auth;
}
@Override
public boolean supports(Class<?> arg0) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(arg0));
}
public String getMD5(String data) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(data.getBytes());
byte[] digest = messageDigest.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
sb.append(Integer.toHexString((int) (b & 0xff)));
}
return sb.toString();
}
}
CustomUserDetailsService
package esercizio.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import esercizio.database.dao.UsersDAO;
import esercizio.database.dto.UsersDTO;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UsersDAO usersDAO;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
UsersDTO userTemp = usersDAO.findByUsername(username);
return userTemp;
}
}
WEB.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>InitServlet</servlet-name>
<servlet-class>esercizio.InitServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/springmvc-servlet.xml
/WEB-INF/spring-security-context.xml
</param-value>
</context-param>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>InitServlet</servlet-name>
<url-pattern>/InitServlet</url-pattern>
</servlet-mapping>
<listener>
<listener-class>esercizio.listener.SessionListener</listener-class>
</listener>
<!-- <filter>
<filter-name>RedirectFilter</filter-name>
<filter-class>esercizio.filters.RedirectFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RedirectFilter</filter-name>
<url-pattern></url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list> -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
Spring-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd
http://www.springframework.org/schema/data/repository
http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd">
<context:component-scan base-package="esercizio" />
<context:annotation-config />
<jpa:repositories base-package="esercizio.database.dao" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- max upload size in bytes -->
<property name="maxUploadSize" value="20971520" /> <!-- 20MB -->
<!-- max size of file in memory (in bytes) -->
<property name="maxInMemorySize" value="1048576" /> <!-- 1MB -->
</bean>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations"
value="classpath:/esercizio/properties/db.properties" />
</bean>
<bean id="JDBCDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="JDBCDataSource" />
</bean>
<!-- <bean id="tjtJTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="JDBCDataSource" />
</bean>
<tx:annotation-driven transaction-manager="tjtJTransactionManager" />-->
<mvc:resources mapping="/resources/**" location="/resources/theme1/"
cache-period="31556926" />
<mvc:annotation-driven />
</beans>
Spring Security xml (it is basically used just to scan and activate annotation config)
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<global-method-security pre-post-annotations="enabled"/>
<context:annotation-config />
<context:component-scan base-package="esercizio" />
</beans:beans>
And last but not least the exception it's giving me
java.lang.NullPointerException
esercizio.security.DbAuthenticationProvider.authenticate(DbAuthenticationProvider.java:41)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
If someone can figure out what the problem is I would be thankful forever, it has been like 3 days and I don't seem to be able to solve it.