我面临一个严重的问题,我无法弄清楚如何解决它。
基本上,在我的自定义身份验证提供程序中,我无法自动装入我的customUserDetailsService,它返回一个空指针异常。
我要粘贴我正在使用的所有类加上异常,这里的问题是它自动装配但它返回NULL,它不会在自动装配本身上给我一个错误。
SecurityConfig类:
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();
}
}
自定义身份验证提供程序:
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>
弹簧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(它主要用于扫描和激活注释配置)
<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>
最后但并非最不重要的是它给我的例外
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)
如果有人能够弄清楚问题是什么,我将永远感恩,这已经过了3天,我似乎无法解决它。
答案 0 :(得分:0)
我认为
@Autowired UserDetailsService customUserDetailsService;
应该是
@Autowired CustomUserDetailsService customUserDetailsService;
答案 1 :(得分:0)
主要原因是,在您configure(AuthenticationManagerBuilder)
DbAuthenticationProvider
中,您正在构建authentication-manager
的新实例,同时将其注入auth.authenticationProvider(new DbAuthenticationProvider());
(仅在此行中:Spring-framework
)在DbAuthenticationProvider
上下文之外,因此注入AuthenticationManager
的{{1}}实例无法autowire
@Autowired UserDetailsService customUserDetailsService
。
由于此UserDetailsService字段为null,因此NullPointerException
方法会在authenticate()
方法中抛出UserDetails user = customUserDetailsService.loadUserByUsername(name);
<{1}}
您可以通过多种方式更改类的加载方式,但最简单的方法是使用此代码块:
@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());
}
并改为:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DbAuthenticationProvider dbAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(dbAuthenticationProvider);
}
我认为这是更改代码以便开始工作的最简单方法