2012-07-07 12 views
7

Estoy intentando asignar a los usuarios de mi base de datos a los usuarios de Spring Security, pero sin mucha suerte. Mi UserServiceImpl es el siguiente (el autowiring normalmente funciona bien cuando estoy llamando a través de un servlet, pero lanza un puntero nulo cuando se utiliza en la primavera de Seguridad ...Excepción del puntero nulo de seguridad de primavera

@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; 
    } 
} 

me sale el siguiente excepción (la primera línea es el 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) 

Así que parece que mi UserDAO no se Autowiring correctamente, pero funciona bien cuando llamo a la capa de servicio desde un servlet, simplemente, aparentemente, no cuando se utiliza primavera-Seguridad.

La línea 40 hace referencia al usuario de devolución Nombre.getByUsername (usern ame)

¿Alguien tiene alguna idea de cómo puedo hacer que el usuario se llene a través de @autowired? Como digo, funciona bien cuando lo llamo a través de un servlet, pero no cuando trato de usar Spring-Security.

¿Hay alguna manera más fácil de asignar usuarios y contraseñas en Spring-security?

Mi seguridad-app-contexto es el siguiente ...

<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> 

Creo que mi pregunta es, ¿por qué es mi UserDAO @Autowired que no trabajan con resorte de seguridad, sin embargo, funciona bien cuando se utiliza en una servlet para devolver el objeto del usuario? Por ejemplo, el siguiente servlet funciona bien ...

¿Por qué mi cableado automático (como arroja un NPE) no funciona cuando está pasando por la seguridad de la primavera, pero funciona bien cuando se lo llama desde un servlet?

EDIT: - añadió

Pero ahora consigo

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'. 

Respuesta

8

Usted se preocupa la creación de su servicio a través de la declaración de frijol:

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

por lo tanto, es necesario configurar como elegible para autowiring estableciendo la propiedad autowire. El valor predeterminado es No. La configuración se verá así:

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

, además, le podría indicar que este bean participará en el proceso de Autowire frijol demás mediante la configuración de la propiedad Autowire-candidata = "true".

Compruebe documentation con el fin de averiguar cuál es la mejor estrategia para que su bean tenga sus propiedades auto conectadas. Yo personalmente uso byType y constructor, pero realmente depende de sus requisitos.

Otra solución sería configurar default-autowire="true" en la etiqueta beans de su contexto.

+0

Agregué pero todavía obtengo un NPE en la misma línea después de reiniciar Tomcat. Pregunta actualizada, pero gracias por el consejo :) – david99world

+0

por favor podría agregar esto a su contexto xml: ' ' –

+0

Además, ya tengo \t en mi contexto servlet, ¿lo necesito en ambos archivos XML? – david99world

2

Creo que acaba de perder <context:annotation-config/> y <context:component-scan base-package="..."/> en su contexto de seguridad de primavera.

+0

Esto da ERROR: org.springframework.web.context.ContextLoader - Inicialización de contexto fallido ... Pregunta actualizada con xml nuevo, gracias por su ayuda :) – david99world

+0

Por supuesto, debe declarar el espacio de nombres de contexto XML al comienzo del XML archivo, como se muestra en http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-annotation-config –

+0

Ah, pensé que lo hizo con xmlns: context = "http://www.springframework.org/schema/context" xmlns: tx = "http://www.springframework.org/schema/tx" – david99world

0

Me acabo de dar cuenta de que tiene el doble de la etiqueta en su archivo xml.

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

Tratemos de eliminarlo.

0

Todo lo que tiene que hacer es sustituir a la seguridad de su aplicación al contexto con esto:

<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 /> 


te extraño escrito algunas piezas, que he corregido para usted.

Cuestiones relacionadas