2011-05-07 11 views
16

में वायर्ड किया गया है, मैं स्प्रिंग 3 और स्प्रिंग सिक्योरिटी का उपयोग कर एक प्रोजेक्ट पर काम कर रहा हूं। मेरी समस्या आईओसी कंटेनर के साथ है। समस्या तब शुरू हुई जब मैंने वसंत सुरक्षा -3 के लिए UserDetailsService का अपना कार्यान्वयन लिखा था। मैंने अन्य प्रश्नों की जांच की लेकिन अभी भी समस्या का समाधान नहीं हो सका। समस्या का@Autowired ऑब्जेक्ट को एक वर्ग में शून्य मान मिलता है, जबकि सफलतापूर्वक दूसरे

परिभाषा है:

मैं दो अलग वर्गों (एक UsersController.java जो @Controller फैली हुई है, और ProjectUserDetailsService जो @Service फैली हुई है) कि एक आम वस्तु autowired जा करने के लिए उपयोग करता है। लेकिन ऑब्जेक्ट को सफलतापूर्वक UsersController में स्वचालित रूप से चालू किया गया है, ProjectUserDetailsService कक्षा में इस वर्ग की वस्तु (ProjectUserDetailsService) सफलतापूर्वक बनाई गई है (मैंने इसे डिबगिंग द्वारा सत्यापित किया है)।

कोई सुझाव यह कैसे हल करें?

यहां मेरे web.xml, project-servlet.xml और project-security.xml फ़ाइलें और संबंधित कक्षाएं हैं।

Web.xml`

<?xml version="1.0" encoding="UTF-8"?> 
<!-- 
    - Tutorial web application 
    - 
    --> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> 
    <display-name>Ecognitio with Spring Security</display-name> 
    <context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
      /WEB-INF/ecognitio-servlet.xml 
      /WEB-INF/ecognitio-security.xml 
     </param-value> 
    </context-param> 
    <context-param> 
    <param-name>webAppRootKey</param-name> 
    <param-value>tutorial.root</param-value> 
    </context-param> 
    <filter> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    <listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <listener> 
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
    </listener> 
    <servlet> 
    <servlet-name>ecognitio</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>project</servlet-name> 
    <url-pattern>*.action</url-pattern> 
    </servlet-mapping> 
    <servlet-mapping> 
    <servlet-name>project</servlet-name> 
    <url-pattern>*.html</url-pattern> 
    </servlet-mapping> 
    <welcome-file-list> 
    <welcome-file>index.jsp</welcome-file> 
    </welcome-file-list> 
</web-app> 

project-servlet.xml

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:p="http://www.springframework.org/schema/p" 
    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"> 

    <!-- Scans the classpath of this application for @Components to deploy as beans --> 
    <context:component-scan base-package="com.project" /> 

    <!-- Configures the @Controller programming model --> 
    <mvc:annotation-driven /> 

    <bean id="messageSource" 
      class="org.springframework.context.support.ResourceBundleMessageSource" 
      p:basename="Messages"/> 

    <!-- misc --> 
<!-- <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> 
     <property name="suffix" value=".jsp"/> 
    </bean> --> 


    <bean id="viewResolver" 
     class="org.springframework.web.servlet.view.UrlBasedViewResolver"> 

     <property name="viewClass"> 
     <value> 
       org.springframework.web.servlet.view.tiles2.TilesView 
      </value> 
     </property> 
    </bean> 

    <bean id="tilesConfigurer" 
    class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"> 
     <property name="definitions"> 
      <list> 
       <value>/WEB-INF/tiles.xml</value> 
      </list> 
     </property> 
    </bean> 

    <!-- Configures Hibernate - Database Config --> 
    <import resource="db-config.xml" /> 
</beans> 

project-security.xml

<?xml version="1.0" encoding="UTF-8"?> 

<!-- 
    - Sample namespace-based configuration 
    - 
    --> 

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

    <debug /> 

    <global-method-security pre-post-annotations="enabled"> 
     <!-- AspectJ pointcut expression that locates our "post" method and applies security that way 
     <protect-pointcut expression="execution(* bigbank.*Service.post*(..))" access="ROLE_TELLER"/> 
     --> 
    </global-method-security> 

    <http pattern="/loggedout.jsp" security="none"/> 

    <http use-expressions="true" > 
     <intercept-url pattern="/secure/extreme/**" access="hasRole('ROLE_SUPERVISOR')"/> 
     <intercept-url pattern="/secure/**" access="isAuthenticated()" /> 

     <!-- 
      Allow all other requests. In a real application you should 
      adopt a whitelisting approach where access is not allowed by default 
      --> 
     <intercept-url pattern="/login.jsp*" access="isAuthenticated()==false"/> 
     <intercept-url pattern="/timeout.jsp*" access="isAuthenticated()==false"/> 
     <intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> 

     <!-- <intercept-url pattern="/**" access="permitAll" /> --> 
     <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/dashboard.html" /> 
     <logout logout-success-url="/login.jsp" delete-cookies="JSESSIONID"/> 
     <remember-me /> 
<!-- 
    Uncomment to enable X509 client authentication support 
     <x509 /> 
--> 
     <!-- Uncomment to limit the number of sessions a user can have 
     <session-management invalid-session-url="/login.jsp"> 
      <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> 
     </session-management> 
     --> 

    </http> 

      <!-- HERE IS WHERE I USE an object of ProjectUserDetailsService --> 
    <authentication-manager> 
     <authentication-provider user-service-ref="userDetailsService" /> 
    </authentication-manager> 


<!-- 

</beans:beans> 

UsersController.java (UsersDAO वर्ग की एक वस्तु की autowiring इस वर्ग के लिए सफल हुआ)

01,235,
package com.project.users; 

//required imports 



@Controller 
public class UsersControllers 
{ 

@Autowired 
private UsersDAO usersDAO; 

    //Some more autowires and some class specific code 


} 

ProjectUserDetailsService.java (जहां UsersDAO की autowiring काम नहीं करता है)

package com.project.security; 

import java.util.ArrayList; 
import java.util.Collection; 

//required imports 


@SuppressWarnings("deprecation") 
@Service("userDetailsService") 
public class ProjectUserDetailsService implements UserDetailsService { 

    @Autowired 
    private UsersDAO usersDAO; 
    @Autowired private Assembler assembler; 

    @Transactional(readOnly = true) 
    public UserDetails loadUserByUsername(String username) 
     throws UsernameNotFoundException, DataAccessException { 

    UserDetails userDetails = null; 
    //For debugging purposes 
    if(usersDAO==null){ 
     System.out.println("DAO IS NULL"); 
     System.out.println("DAO IS NULL"); 
     System.out.println("DAO IS NULL"); 

    } 
    User userEntity = usersDAO.findUserbyEmail("'"+username+"'"); 


    if (userEntity == null) 
     throw new UsernameNotFoundException("user not found"); 

    return assembler.buildUserFromUserEntity(userEntity); 

    } 
} 
+1

मुझे 'project-securityDxS' में 'ProjectUserDetailsService' में कोई संदर्भ नहीं दिखता है। क्या यह गायब है? – skaffman

+0

ProjectUserDetailsService.java को @Service ("userDetailsService") के रूप में परिभाषित किया गया है, इस नाम के साथ एक बीन बूटस्ट्रैप पर बनाया गया है। तो यह समस्या नहीं है। –

उत्तर

1

के बाद से दूसरा सेम निर्दिष्ट सेम एनोटेशन पैकेज घटक स्कैन project-servlet.xml में विनिर्दिष्ट में नहीं है:

<context:component-scan base-package="com.project" /> 

यह करता है इसे एक सेवा नहीं मानते हैं और एनोटेशन का अनुवाद नहीं करते हैं।

आप इसे आगे बढ़ाने या एक पैकेज पर ले जाते हैं com.project साथ वरना इस तरह शुरू करने की जरूरत है:

<context:component-scan base-package="com" /> 
+0

मुझे खेद है, मैंने गलत टाइप किया था। ProjectUserDetailsService.java वास्तव में com.project पैकेज में है। तो यह समस्या नहीं है। नाम उपयोगकर्ता DetailsService (ProjectUserDetailsService) के साथ एक बीन बनाया गया है लेकिन इसकी निर्भरता स्वचालित नहीं है। मैंने सवाल को सही किया। –

4

हाँ, यह या सेम कि वसंत सुरक्षा वर्गों से विरासत में वस्तुओं autowire करने के लिए असंभव प्रतीत हो रहा है, तो इस वसंत में सुरक्षा में एक बग है। मुझे पता नहीं है, अगर यह है सुरक्षा के लिए किया गया या क्या। अगर किसी के पास स्पष्टीकरण है मैं इसे सुनने में दिलचस्पी लेता हूं। आप अपनी समस्या को हल कर सकते हैं हालांकि मैन्युअल रूप से एक्सएमएल कॉन्फ़िगरेशन के माध्यम से बीन्स इंजेक्शन करके (@Autowired एनोटेशन का उपयोग करने के विपरीत) और फिर वे उपस्थित होंगे। सावधानी बरतने का एक शब्द ..

मैंने यह किया, और मैंने देखा कि मेरे उपयोगकर्तादाओ जिस पर एनोटेशन था (विशेष रूप से @ ट्रांसेक्शनल) अब लेनदेन में काम नहीं कर रहा था।मेरे उपयोगकर्तादाओ का इस्तेमाल कई स्थानों पर किया जा रहा था। अगर मैंने इसे अपने कस्टम AbstractUserDetailsAuthenticationProvider में इंजेक्शन दिया है, तो यह अब किसी भी अन्य वर्ग के लिए लेनदेन में संचालित नहीं होता है। कस्टम AbstractUserDetailsAuthenticationPproider में इंजेक्शन को हटाकर मेरे उपयोगकर्ता को लेनदेन कार्यक्षमता बहाल कर दी गई है जब इसे प्राप्त करने वाले अन्य ऑब्जेक्ट्स द्वारा उपयोग किया जाता है (या तो @Autowired या मैन्युअल xml इंजेक्शन के माध्यम से)।

तो मैं अपने उपयोगकर्ताडाओ को अपने वसंत सुरक्षा संदर्भ में कैसे प्राप्त करूं और अभी भी इसे @ ट्रान्सएक्शनल रखें?

public class UserDaoFactory { 

private static UserDao userDao; 

public static UserDao getUserDao() { 
    return UserDaoFactory.userDao; 
} 

public void setUserDao(UserDao userDao) { 
    UserDaoFactory.userDao = userDao; 
} 
} 

तो वसंत कंटेनर में इस और अपने दाव दो वस्तुओं डाल:

<bean id="userDao" class="com.package.UserDaoImpl"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<bean id="userDaoFactory" class="com.package.UserDaoFactory"> 
    <property name="userDao" ref="userDao" /> 
</bean> 

तो userDao अपने userDaoFactory में autowired हो जाएगी मैं एक फैक्टरी वर्ग बनाने के लिए किया था। इसमें इसकी सभी @ ट्रान्सैक्शनल क्षमता होगी (क्योंकि वसंत सुरक्षा ने इसे छीन लिया नहीं है?)। फिर अपने वसंत सुरक्षा वस्तु में आप एक कर सकते हैं:

userDao = UserDaoFactory.getUserDao(); 

मैं आरंभीकरण के दौरान अपने कस्टम वस्तु AbstractUserDetailsAuthenticationProvider ऊपर एक बार ऐसा करने के लिए ServletContextAware लागू किया, और वाइला।

तो ध्यान दें, जबकि आप @Autowired समस्या को दूर करने के लिए वसंत सुरक्षा ऑब्जेक्ट में एक्सएमएल कॉन्फ़िगरेशन के माध्यम से मैन्युअल रूप से अपने बीन इंजेक्ट कर सकते हैं, तो आप एक नई समस्या के साथ समाप्त हो जाएंगे यदि आप उस डीएओ को @ ट्रान्सैक्शन में लपेटने की कोशिश कर रहे हैं।

अब शायद कोई जानता है कि यह क्यों हो रहा है। यह मेरे हिस्से पर एक गलत कॉन्फ़िगरेशन हो सकता है (मैं मानता हूं कि मैं वसंत विशेषज्ञ नहीं हूं), या यह वसंत की एक विशेषता हो सकती है। मुझे यह सुनना अच्छा लगेगा कि किसी को क्या कहना है और इसे कैसे सुधारना है।

0

यह SEC-1911 के कारण होने की संभावना है जो AutowiredAnnotationBeanPostProcessor जैसे बीनपोस्टप्रोसेसरों पर निर्भर करते समय और <debug /> तत्व का उपयोग करते समय समस्याएं उत्पन्न करता है। <debug /> को हटाने का प्रयास करें और देखें कि @Autowired फिर से काम करता है या नहीं। ध्यान दें कि यह पहला मुद्दा SEC-1885 का डुप्लिकेट है, जहां यह तय किया गया है लेकिन पहले मुद्दे के लक्षण इस मुद्दे से बेहतर मेल खाते हैं।

-1

मुझे एक ही समस्या थी। यद्यपि यह कई तरीकों से हो सकता है, मेरे मामले में मैं autowired एक का उपयोग करने के बजाय, एक नई वस्तु बना रहा था। यानी .:

private Service service = new ServiceImpl(); 

के बजाय:

@Autowired private Service service; 

यह भंडार इंजेक्शन का उपयोग करके सेवा में नहीं था, लेकिन उसके ऊपर एक नियंत्रक में।

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