2012-07-09 26 views
0

我正在使用具有自定義UserDetailsS​​ervice的spring-security進行基於表單的登錄。登錄表單似乎正確提交。在調試應用程序時,我發現提交的請求已到達UsernamePasswordAuthenticationFilter的attemptAuthentication方法。但它看起來像請求參數不能映射到用戶名和密碼字段,因爲它們保持爲空。因此,我的自定義UserDetailsS​​ervice的loadByUsername方法的參數用戶名仍爲空,我無法成功登錄。自定義UserDetailsS​​ervice中loadUserByUsername的參數用戶名始終爲空

我試了很多,但現在我不知道問題可能是什麼。我對春季保安也很陌生,但我想我並不太遠。

我儘可能地總結了代碼。如果您需要更多信息,請立即告訴我。

首先,我成立了springSecurityFilterChain在web.xml:

<welcome-file-list> 
    <welcome-file>index.xhtml</welcome-file> 
</welcome-file-list> 

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
     classpath:WEB-INF/applicationContext.xml, 
     classpath:WEB-INF/applicationContext-security.xml 
    </param-value> 
</context-param> 

<context-param> 
    <param-name>log4jConfigLocation</param-name> 
    <param-value>classpath:log4j.properties</param-value> 
</context-param> 

<!-- Filter Config --> 
<filter> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<!-- Filter Mappings --> 
<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
    <dispatcher>REQUEST</dispatcher> 
</filter-mapping> 

<!-- Spring Configuration --> 
<listener> 
    <listener-class> 
     org.springframework.web.context.ContextLoaderListener 
    </listener-class> 
</listener> 
<listener> 
    <listener-class> 
     org.springframework.web.context.request.RequestContextListener 
    </listener-class> 
</listener> 

這是我的applicationContext.xml與參考customUserDetailsS​​ervice:

<bean id="propertyConfigurer" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    ... 
</bean> 

<bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    ... 
</bean> 

<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    ... 
</bean> 

<!-- Authentification --> 
<bean id="customUserDetailsService" class="com.seraphim.security.auth.CustomUserDetailsService"/> 

<!-- Transaction --> 
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/> 

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

<context:annotation-config/> 

<tx:annotation-driven transaction-manager="transactionManager"/> 

的具有適當的證書的applicationContext-security.xml ication提供商:

<http 
    auto-config="true" 
    access-denied-page="/accessDenied.jsp"> 

    <intercept-url 
      pattern="/pages/**" 
      access="ROLE_ADMIN,ROLE_USER"/> 
    <intercept-url 
      pattern="/**" 
      access="IS_AUTHENTICATED_ANONYMOUSLY"/> 

    <form-login 
      login-processing-url="/j_spring_security_check" 
      login-page="/index.xhtml" 
      default-target-url="/pages/main.xhtml" 
      authentication-failure-url="/index.xhtml"/> 

    <logout 
      logout-url="/logout*" 
      logout-success-url="/"/> 

</http> 

<authentication-manager> 
    <authentication-provider user-service-ref="customUserDetailsService"> 
     <password-encoder hash="md5"/> 
    </authentication-provider> 
</authentication-manager> 

在faces-config.xml中我添加了一個LoginErrorPhaseListener檢測BadCredentialsException和添加的LoginBean:

<lifecycle> 
    <phase-listener>com.seraphim.security.auth.LoginErrorPhaseListener</phase-listener> 
</lifecycle> 

<managed-bean> 
    <managed-bean-name>loginBean</managed-bean-name> 
    <managed-bean-class> 
     com.seraphim.bean.LoginBean 
    </managed-bean-class> 
    <managed-bean-scope> 
     request 
    </managed-bean-scope> 
</managed-bean> 

的index.xhtml是具有用戶名密碼字段an提交給loginBean:

<h:form id="loginForm"> 

    <h:outputLabel for="j_username" value="User:"/> 
    <p:inputText id='j_username' label="user" required="true"/> 

    <h:outputLabel for="j_password" value="Password:"/> 

    <h:inputSecret id='j_password' label="pass2" required="true"/> 

    <h:outputLabel for="_spring_security_remember_me" value="Remember "/> 
    <p:selectBooleanCheckbox id='_spring_security_remember_me'/> 

    <h:outputLabel/> 
    <h:commandButton type="submit" id="login" action="#{loginBean.doLogin}" value="Login"/> 

</h:form> 

LoginBean.java

@Component 
@Scope("request") 
public class LoginBean { 

    public String doLogin() throws IOException, ServletException { 

    ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); 

    RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()) 
      .getRequestDispatcher("/j_spring_security_check"); 

    dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse()); 

    FacesContext.getCurrentInstance().responseComplete(); 

    // It's OK to return null here because Faces is just going to exit. 
    return null; 

    } 
} 

現在CustomUserDetailsS​​ervice.java正確的用戶應該被加載,但這裏的方法參數的用戶名始終是空的(不是null)。因此,當然沒有有效的用戶被發現:

public class CustomUserDetailsService implements UserDetailsService { 

@Resource 
IUserDao userDao; 

@Override 
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 

    User user = userDao.findByUsername(username); 

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

    // build roles for user 
    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    authorities.add(new GrantedAuthorityImpl("ROLE_USER")); 
    if(user.isAdmin()) { 
     authorities.add(new GrantedAuthorityImpl("ROLE_ADMIN")); 
    } 

    return new org.springframework.security.core.userdetails.User(
      user.getUsername(), 
      user.getPassword(), 
      user.isEnabled(), 
      user.isAccountNonExpired(), 
      user.isCredentialsNonExpired(), 
      user.isAccountNonLocked(), 
      authorities); 
} 

} 

希望你能幫助我在這一個。

回答

1

如果這樣,你需要設置你的形式prependId = "false"結合春季安全與JSF,Spring Security中另有要求的字段名稱將與表單ID預先考慮:

<h:form id="loginForm" prependId = "false">...</h:form> 
+0

這做的伎倆!感謝您的解決方案。 – tobiasdenzler 2012-07-09 08:01:17

相關問題