2012-07-07 4 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을 정상적으로 내가 서블릿을 통해 호출있을 때 잘 작동하지만 봄 보안 사용할 때 널 포인터를 던졌습니다입니다 (첫 번째 줄 내 userDao가 제대로 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) 

그래서 보이는,하지만 난 봄 - 보안을 사용하여 단지 분명히하지 않을 경우, 서블릿에서 서비스 레이어를 호출 할 때 그것을 잘 작동합니다.

라인 40은 return userDao.getByUsername (usern ame);

@autowired를 통해 userDao를 채우는 방법에 대한 아이디어가있는 사람이 있습니까? 내가 말했듯이 스프링 보안을 사용하려고 할 때가 아니라 서블릿을 통해 호출 할 때 제대로 작동합니다.

스프링 보안에서 사용자와 비밀번호를 쉽게 매핑 할 수 있습니까? 다음과 같이

내 보안 앱 컨텍스트가 ... 내 질문은 생각

<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 봄 보안 작동하지 않습니다, 아직 사용할 때 그것을 잘 작동합니다 서블릿에서 사용자 객체를 반환하겠습니까? 예를 들어, 다음 서블릿이 잘 작동합니다 ...

스프링 보안을 통과 할 때 autowiring (NPE가 throw 됨)되어 작동하지 않는 이유는 무엇입니까? 서블릿에서 호출 할 때 제대로 작동하는 이유는 무엇입니까?

편집 : -

을 추가하지만 지금 당신은 빈 선언을 통해 서비스를 만드는 신경

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

추가로이 빈은 속성 자동으로 묶어 후보는 = "true"를 구성하여 다른 콩 자동으로 묶어 과정에 참여하는 것을 나타낼 수 있습니다 : 같은 구성은 볼 것이다.

확인하십시오. 빈에 대한 최상의 전략 중 autowired 속성을 찾으려면 documentation을 확인하십시오. 나는 개인적으로 byTypeconstructor을 사용하지만, 그것은 당신의 요구에 정말로 달려 있습니다.

또 다른 해결책은 컨텍스트의 beans 태그에서 default-autowire="true"을 구성하는 것입니다.

+0

을 추가했지만 Tomcat을 다시 시작한 후에도 여전히 같은 줄에 NPE가 있습니다. 업데이트 된 질문이지만 조언을 주셔서 감사합니다. – david99world

+0

이 내용을 컨텍스트 xml에 추가 할 수 있습니까? ' –

+0

또한, 이미 \t을 가지고 있습니다. 내 서블릿 컨텍스트에서 두 XML 파일 모두에서 필요합니까? – david99world

2

스프링 보안 컨텍스트에서 <context:annotation-config/><context:component-scan base-package="..."/>을 놓친 것 같습니다.

+0

다음과 같이 에러가 발생합니다 : org.springframework.web.context.ContextLoader - 컨텍스트 초기화에 실패했습니다 ... 새 xml로 업데이트 된 질문, 감사합니다 :) – david99world

+0

물론 XML 시작 부분에 XML 컨텍스트 네임 스페이스를 선언해야합니다 http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-annotation-config –

+0

에 나와있는 것처럼 아, xmlns : context = "http://www.springframework.org/schema/context"xmlns : tx = "http://www.springframework.org/schema/tx" – david99world

0

xml 파일의 태그가 두 배로 증가했습니다.

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


당신은 내가 당신을 위해 수정 일부를 입력 그리워.