2012-07-07 18 views
7

मैं अपने डेटाबेस में उपयोगकर्ताओं को स्प्रिंग सुरक्षा उपयोगकर्ताओं को मैप करने की कोशिश कर रहा हूं, लेकिन बिना किस्मत के। मेरे UserServiceImplस्प्रिंग सुरक्षा नल पॉइंटर अपवाद

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

मैं निम्नलिखित अपवाद के रूप में निम्नानुसार (autowiring सामान्य रूप से ठीक है जब मैं एक सर्वलेट के माध्यम से फोन कर रहा हूँ काम करता है, लेकिन जब वसंत सुरक्षा में इस्तेमाल एक अशक्त सूचक फेंकता है ... (पहली पंक्ति 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 तरह सही ढंग से autowiring नहीं है, लेकिन यह ठीक काम करता है जब मैं एक सर्वलेट से सेवा परत कहते हैं, वसंत-सुरक्षा का उपयोग कर बस जाहिरा तौर पर नहीं है।

लाइन 40 उपयोगकर्ता को वापस करने का संदर्भ देता है Dao.getByUsername (usern एएमई);

क्या किसी के पास कोई विचार है कि मैं उपयोगकर्ता को कैसे प्राप्त कर सकता हूं @autowired के माध्यम से पॉप्युलेट किया जा सकता है? जैसा कि मैंने कहा, यह ठीक काम करता है जब मैं इसे सर्वलेट के माध्यम से बुलाता हूं, बस वसंत-सुरक्षा का उपयोग करने की कोशिश करते समय नहीं।

क्या स्प्रिंग-सुरक्षा में उपयोगकर्ता और पासवर्ड मैप करने का कोई आसान तरीका है?

मेरे सुरक्षा एप्लिकेशन के संदर्भ इस प्रकार है ...

<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 वसंत-सुरक्षा के साथ काम नहीं कर रहा है, फिर भी यह ठीक काम करता है जब एक में इस्तेमाल किया उपयोगकर्ता ऑब्जेक्ट को वापस करने के लिए सर्वलेट? उदाहरण के लिए, निम्नलिखित सर्वलेट ठीक काम करता है ...

मेरी ऑटोवॉयरिंग (जैसा कि यह एनपीई फेंकता है) क्यों वसंत-सुरक्षा के माध्यम से काम नहीं कर रहा है, फिर भी यह सर्वलेट से बुलाए जाने पर ठीक काम करता है?

संपादित करें: - जोड़ा

लेकिन अब मैं

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

उत्तर

8

मिल आप सेम घोषणा के माध्यम से आपकी सेवा बनाने परवाह:

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

इसलिए आप autowiring के लिए पात्र के रूप में यह विन्यस्त करने की जरूरत संपत्ति autowire सेट करके। डिफ़ॉल्ट No है।

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

अतिरिक्त आप का संकेत हो सकता है कि इस सेम संपत्ति autowire उम्मीदवार = "true" कॉन्फ़िगर करके दूसरों सेम autowire प्रक्रिया में भाग लेंगे: की तरह विन्यास दिखेगा।

अपने बीन के लिए सबसे अच्छी रणनीति कौन सा है, यह जानने के लिए documentation देखें। मैं व्यक्तिगत रूप से byType और constructor का उपयोग करता हूं, लेकिन यह वास्तव में आपकी आवश्यकता पर निर्भर करता है।

एक और समाधान आपके संदर्भ के beans टैग default-autowire="true" पर कॉन्फ़िगर किया जाएगा।

+0

मैंने <बीन्स: बीन क्लास = "org.assessme.com.service.UserServiceImpl" id = "UserDetailsService" autowire = "byType" /> जोड़ा लेकिन मुझे अभी भी टोमकैट को पुनरारंभ करने के बाद एक ही पंक्ति पर एनपीई मिलता है। अद्यतन प्रश्न, लेकिन सलाह के लिए धन्यवाद :) – david99world

+0

कृपया इसे अपने संदर्भ में जोड़ सकते हैं xml: '<संदर्भ: एनोटेशन-कॉन्फ़िगरेशन /> ' –

+0

इसके अलावा, मेरे पास पहले से ही \t <संदर्भ: घटक-स्कैन बेस-पैकेज =" org.assessme.com है। " /> मेरे सर्वलेट संदर्भ में, क्या मुझे इसे एक्सएमएल फाइलों में चाहिए? – david99world

2

मुझे लगता है कि आप बस वसंत-सुरक्षा संदर्भ में <context:annotation-config/> और <context:component-scan base-package="..."/> से चूक गए हैं।

+0

यह त्रुटि देता है: org.springframework.web.context.ContextLoader - संदर्भ प्रारंभिक विफल रहा ... नए एक्सएमएल के साथ अद्यतन प्रश्न, आपकी मदद के लिए धन्यवाद :) – david99world

+0

आपको एक्सएमएल की शुरुआत में एक्सएमएल संदर्भ नामस्थान घोषित करने की ज़रूरत है फ़ाइल, जैसा कि http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-annotation-config –

+0

में दिखाया गया है, मैंने सोचा कि मैं क्या xmlns के साथ किया गया: संदर्भ = "http://www.springframework.org/schema/context" xmlns: tx = "http://www.springframework.org/schema/tx" – david99world

0

मुझे लगता है कि आपने अपनी एक्सएमएल फ़ाइल में टैग को दोगुना कर दिया है।

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

चलो इसे हटाने का प्रयास करें।

0

आपको बस इतना करना है इस के साथ अपने सुरक्षा एप्लिकेशन के संदर्भ को बदलने के लिए है:

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


आप कुछ भागों, जो मैं आप के लिए सही टाइप किया चूक जाएं।

संबंधित मुद्दे