首页 > 解决方案 > UserDetailsS​​ervice 中的 UserRepository 为空

问题描述

我正在使用 Spring 3.0.7,并通过UserDetailsServicespring-secrutiy.xml 创建了 bean,以将其用作用户的提供者

<authentication-manager>
    <authentication-provider user-service-ref='userDetailsService'>
        <password-encoder hash="sha"/>
    </authentication-provider>
</authentication-manager>

不幸的是, userRepository 是 null 我不知道为什么,所以我在对其对象执行操作时得到 NPE。

16-Dec-2020 21:20:16.700 SEVERE [http-nio-8080-exec-6] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [DispatcherServlet] in context with path [/fitnessapplication_war_exploded] threw exception
    java.lang.NullPointerException
        at main.configuration.UserDetailsServiceImpl.loadUserByUsername(UserDetailsServiceImpl.java:25)
        at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:86)
        at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:129)
        at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:130)
        at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48)
        at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:148)
        at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48)
        at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:142)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
        at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:168)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:544)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:616)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1634)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

用户详情服务

package main.configuration;

import lombok.NoArgsConstructor;
import main.model.user.User;
import main.user.UserRepository;
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;

@Service
@NoArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private UserRepository userRepository;

    @Autowired
    public UserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user != null) {
            return user;
        } else {
            throw new UsernameNotFoundException("Not found: " + username);
        }
    }
}

在应用程序启动时,我将一些初始数据添加到 DB 中,因此必须创建 UserRepository 的 bean,但我不知道为什么它在 UserDetailsS​​erviceImpl 中被视为 null。

Spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             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/security
    http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/asd" access="permitAll"/>
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
        <intercept-url pattern="/users" access="hasRole('ROLE_ADMIN')"/>
        <http-basic/>
    </http>

    <beans:bean name="userDetailsService" class="main.configuration.UserDetailsServiceImpl"/>

    <authentication-manager>
        <authentication-provider user-service-ref='userDetailsService'>
            <password-encoder hash="sha"/>
        </authentication-provider>
    </authentication-manager>


    <beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
        <beans:constructor-arg value="256"/>
    </beans:bean>
</beans:beans>

你能告诉我这里有什么问题吗?

标签: javaspring-securitynullpointerexceptionuserdetailsservice

解决方案


  1. 选项:将@Autowired注释放在userRepository变量之前。
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user != null) {
            return user;
        } else {
            throw new UsernameNotFoundException("Not found: " + username);
        }
    }
}
  1. 选项:使用构造函数更改服务 XML 声明。我假设UserRepositorybean 名称是userRepository.
<beans:bean name="userDetailsService" class="main.configuration.UserDetailsServiceImpl">
 <constructor-arg index="0" ref="userRepository"/>
</beans:bean>

... 代替

<beans:bean name="userDetailsService" class="main.configuration.UserDetailsServiceImpl"/>

推荐阅读