2012-07-07 50 views
7

Tôi đang cố gắng lập bản đồ người dùng trong cơ sở dữ liệu của mình cho người dùng Spring Security, nhưng không có nhiều may mắn. UserServiceImpl của tôi là như sau (các autowiring thường hoạt động tốt khi tôi gọi đó là thông qua một servlet, nhưng ném một con trỏ null khi sử dụng trong mùa xuân an ninh ...Bảo mật mùa xuân null pointer exception

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

tôi nhận được ngoại lệ sau (dòng đầu tiên là 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) 

Vì vậy, nó trông giống như userDao của tôi không autowiring một cách chính xác, nhưng nó hoạt động tốt khi tôi gọi là lớp dịch vụ từ một servlet, chỉ rõ ràng không phải khi sử dụng Spring-Security.

Dòng 40 đề cập đến việc trả lại userDao.getByUsername (usern ame);

Có ai có bất kỳ ý tưởng nào về cách tôi có thể yêu cầu userDao được điền thông qua @autowired không? Như tôi đã nói, nó hoạt động tốt khi tôi gọi nó thông qua một servlet, không phải khi cố gắng sử dụng bảo mật mùa xuân.

Có cách nào dễ dàng hơn để tôi có thể ánh xạ người dùng và mật khẩu trong Spring-security không?

an ninh-app-bối cảnh của tôi là như sau ...

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

Tôi đoán câu hỏi của tôi là, tại sao là userDao @Autowired tôi không làm việc với mùa xuân-an ninh, nhưng nó hoạt động tốt khi sử dụng trong một servlet để trả về đối tượng người dùng? Ví dụ, servlet sau hoạt động tốt ...

Tại sao autowiring của tôi (vì nó ném NPE) không hoạt động khi nó đi qua bảo mật mùa xuân, nhưng nó hoạt động tốt khi được gọi từ servlet?

EDIT: - thêm

Nhưng bây giờ tôi nhận được

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

Trả lời

8

Bạn quan tâm đến việc tạo ra dịch vụ của bạn thông qua tuyên bố đậu:

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

do đó bạn cần phải cấu hình nó như là hội đủ điều kiện cho autowiring bằng cách đặt thuộc tính autowire. Mặc định là No. Cấu hình sẽ trông giống như:

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

Ngoài ra bạn có thể chỉ ra rằng bean này sẽ tham gia vào quá trình tự động đậu khác bằng cách định cấu hình thuộc tính autowire-candidate = "true".

Kiểm tra documentation để tìm ra chiến lược nào tốt nhất cho hạt của bạn có đặc tính tự động. Cá nhân tôi sử dụng byTypeconstructor, nhưng điều đó tùy thuộc vào yêu cầu của bạn.

Một giải pháp khác sẽ được định cấu hình default-autowire="true" trong thẻ beans trong ngữ cảnh của bạn.

+0

Tôi đã thêm nhưng tôi vẫn nhận được một NPE trên cùng một dòng sau khi khởi động lại Tomcat. Câu hỏi được cập nhật, nhưng cảm ơn bạn vì lời khuyên :) – david99world

+0

vui lòng bạn có thể thêm điều này vào ngữ cảnh của bạn xml: ' ' –

+0

Ngoài ra, tôi đã có \t trong ngữ cảnh servlet của tôi, tôi có cần nó trong cả hai tệp XML không? – david99world

2

Tôi nghĩ bạn vừa bỏ lỡ <context:annotation-config/><context:component-scan base-package="..."/> trong bối cảnh bảo mật mùa xuân.

+0

Điều này cho ERROR: org.springframework.web.context.ContextLoader - Bối cảnh khởi tạo không thành công ... Cập nhật câu hỏi với xml mới, cảm ơn sự giúp đỡ của bạn :) – david99world

+0

Tất nhiên bạn cần khai báo không gian tên ngữ cảnh XML ở đầu XML tệp, như được hiển thị trong http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-annotation-config –

+0

Ah, tôi nghĩ tôi đã làm điều đó với xmlns: context = "http://www.springframework.org/schema/context" xmlns: tx = "http://www.springframework.org/schema/tx" – david99world

0

Tôi chỉ nhận thấy rằng bạn đã tăng gấp đôi thẻ trong tệp xml của mình.

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

Hãy thử xóa nó.

0

Tất cả bạn phải làm là để thay thế an ninh-app-ngữ cảnh của bạn với điều này:

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


bạn bỏ lỡ gõ một số bộ phận, mà tôi sửa lại cho bạn.

Các vấn đề liên quan