【问题标题】:Spring security null pointer exceptionSpring安全空指针异常
【发布时间】:2012-07-07 15:53:38
【问题描述】:

我正在尝试将数据库中的用户映射到 Spring Security 用户,但运气不佳。我的 UserServiceImpl 如下(当我通过 servlet 调用它时,自动装配通常工作正常,但在 Spring Security 中使用时会抛出一个空指针......

@Service("userService")
@Transactional
public class UserServiceImpl implements UserService, UserDetailsService {

    protected static Logger logger = Logger.getLogger("service");

    @Autowired
    private UserDAO userDao;

    public UserServiceImpl() {
    }

    @Transactional
    public User getById(Long id) {
        return userDao.getById(id);
    }

    @Transactional
    public User getByUsername(String username) {
        return userDao.getByUsername(username);
    }

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {

        UserDetails user = null;
        try {
            System.out.println(username);
            User dbUser = getByUsername(username);

            user = new org.springframework.security.core.userdetails.User(
                    dbUser.getUsername(), dbUser.getPassword(), true, true,
                    true, true, getAuthorities(dbUser.getAccess()));
        } catch (Exception e) {
            e.printStackTrace();
            logger.log(Level.FINE, "Error in retrieving user");
            throw new UsernameNotFoundException("Error in retrieving user");
        }

        // Return user to Spring for processing.
        // Take note we're not the one evaluating whether this user is
        // authenticated or valid
        // We just merely retrieve a user that matches the specified username
        return user;
    }

    public Collection<GrantedAuthority> getAuthorities(Integer access) {
        // Create a list of grants for this user
        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);

        // All users are granted with ROLE_USER access
        // Therefore this user gets a ROLE_USER by default
        logger.log(Level.INFO, "User role selected");
        authList.add(new GrantedAuthorityImpl("ROLE_USER"));

        // Check if this user has admin access
        // We interpret Integer(1) as an admin user
        if (access.compareTo(1) == 0) {
            // User has admin access
            logger.log(Level.INFO, "Admin role selected");
            authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
        }

        // Return list of granted authorities
        return authList;
    }
}

我得到以下异常(第一行是 System.out)

dusername
java.lang.NullPointerException
    at org.assessme.com.service.UserServiceImpl.getByUsername(UserServiceImpl.java:40)
    at org.assessme.com.service.UserServiceImpl.loadUserByUsername(UserServiceImpl.java:50)
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:81)
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:132)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:194)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:722)

所以看起来我的 userDao 没有正确自动装配,但是当我从 servlet 调用服务层时它工作正常,只是在使用 Spring-Security 时显然不行。

第 40 行指 return userDao.getByUsername(username);

有没有人知道如何通过@autowired 填充 userDao?正如我所说,当我通过 servlet 调用它时它工作正常,只是在尝试使用 spring-security 时不行。

有没有更简单的方法可以在 Spring-security 中映射用户和密码?

我的安全应用上下文如下...

<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.1.xsd"
                    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx">
<context:annotation-config />
<context:component-scan base-package="org.assessme.com." />


    <http pattern="/static/**" security="none" />
    <http use-expressions="true">
        <intercept-url pattern="/login" access="permitAll" />
        <intercept-url pattern="/*" access="isAuthenticated()" />
        <!-- <intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')" 
            /> -->
        <!-- <intercept-url pattern="/listAccounts.html" access="isAuthenticated()" 
            /> -->
        <!-- <intercept-url pattern="/post.html" access="hasAnyRole('supervisor','teller')" 
            /> -->
<!--        <intercept-url pattern="/*" access="denyAll" /> -->
        <form-login />
        <logout invalidate-session="true" logout-success-url="/"
            logout-url="/logout" />
    </http>

    <authentication-manager>
        <authentication-provider user-service-ref="UserDetailsService">
          <password-encoder ref="passwordEncoder"/>
        </authentication-provider>
</authentication-manager>
<context:component-scan base-package="org.assessme.com" /><context:annotation-config />
<beans:bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>

<beans:bean class="org.assessme.com.service.UserServiceImpl" id="UserDetailsService" autowire="byType"/>


</beans:beans> 

我想我的问题是,为什么我的 userDao @Autowired 不能与 spring-security 一起使用,但在 servlet 中用于返回用户对象时却可以正常工作?例如,以下 servlet 可以正常工作...

为什么我的自动装配(因为它会引发 NPE)在通过 spring-security 时不起作用,但在从 servlet 调用时却可以正常工作?

编辑:- 添加

但现在我明白了

ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 9 in XML document from ServletContext resource [/WEB-INF/spring/security-app-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 30; cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'context:annotation-config'.

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    你关心通过 bean 声明创建你的服务:

    <beans:bean class="org.assessme.com.service.UserServiceImpl" id="UserDetailsService"/>
    

    因此,您需要通过设置属性autowire 将其配置为符合自动装配条件。默认为No。配置将如下所示:

    <beans:bean class="org.assessme.com.service.UserServiceImpl" id="UserDetailsService"  autowire="byType" />
    

    此外,您可以通过配置属性 autowire-candidate="true" 来指示此 bean 将参与其他 bean 自动装配过程。

    检查documentation 以找出最适合您的 bean 的策略,使其属性自动装配。我个人使用byTypeconstructor,但这取决于您的要求。

    另一种解决方案是在您的上下文的标签beans 中配置default-autowire="true"

    【讨论】:

    • 我添加了 但之后我仍然在同一行得到 NPE重新启动 Tomcat。更新了问题,但感谢您的建议:)
    • 请您将其添加到您的上下文中 xml:&lt;context:component-scan base-package="org.assessme.com" /&gt;&lt;context:annotation-config /&gt;
    • 另外,我已经有了 在我的 servlet-context 中,两个 XML 文件都需要它吗?
    • 您在工作环境中需要它。在这种情况下,您在问题上发布的文件。
    • 啊,好的,我现在遇到了一个不同的异常,尽管使用了上下文:
    【解决方案2】:

    我认为您只是错过了 spring-security 上下文中的 &lt;context:annotation-config/&gt;&lt;context:component-scan base-package="..."/&gt;

    【讨论】:

    【解决方案3】:

    我只是注意到您在 xml 文件中将标签加倍了。

    <context:component-scan base-package="org.assessme.com" /><context:annotation-config />
    

    让我们尝试删除它。

    【讨论】:

      【解决方案4】:

      您所要做的就是将您的 security-app-context 替换为:

      <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.1.xsd"
                      xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx">
      
      <context:annotation-config>
      <context:component-scan base-package="org.assessme.com." />
      
      <http pattern="/static/**" security="none" />
      <http use-expressions="true">
          <intercept-url pattern="/login" access="permitAll" />
          <intercept-url pattern="/*" access="isAuthenticated()" />
          <!-- <intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')" 
              /> -->
          <!-- <intercept-url pattern="/listAccounts.html" access="isAuthenticated()" 
              /> -->
          <!-- <intercept-url pattern="/post.html"     access="hasAnyRole('supervisor','teller')" 
              /> -->
      <!--        <intercept-url pattern="/*" access="denyAll" /> -->
          <form-login />
          <logout invalidate-session="true" logout-success-url="/"
              logout-url="/logout" />
      </http>
      <authentication-manager>
          <authentication-provider user-service-ref="UserDetailsService">
            <password-encoder ref="passwordEncoder"/>
          </authentication-provider>
      </authentication-manager>
      <context:annotation-config />
      


      你错过了输入的一些部分,我为你更正了。

      【讨论】:

        猜你喜欢
        • 2020-06-01
        • 2014-04-13
        • 2017-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-17
        • 2018-10-01
        • 2019-02-06
        相关资源
        最近更新 更多