2011-03-30 225 views
1

我正在实现spring security 3.0.5,并在我的基于表单的登录im扩展了UserDetailsS​​ervice。目前我的登录表单只是验证用户名而不是密码。 spring安全在哪里验证发布到/ j_spring_security_check的密码?Spring Security UserDetailsS​​ervice不验证密码

安全配置:

<?xml version="1.0" encoding="UTF-8"?> 
<beans:beans 
    xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:context="http://www.springframework.org/schema/context" 
    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/util 
    http://www.springframework.org/schema/util/spring-util-3.0.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
    <context:annotation-config /> 
    <context:component-scan base-package="dc" /> 
    <global-method-security /> 
    <http access-denied-page="/auth/denied.html"> 
     <intercept-url filters="none" pattern="/javax.faces.resource/**" /> 
     <intercept-url filters="none" pattern="/services/rest-api/1.0/**" /> 
     <intercept-url filters="none" pattern="/preregistered/*"/> 
     <intercept-url 
      pattern="/**/*.xhtml" 
      access="ROLE_NONE_GETS_ACCESS" /> 
     <intercept-url 
      pattern="/auth/**" 
      access="ROLE_ANONYMOUS,ROLE_USER" /> 
     <intercept-url 
      pattern="/auth/*" 
      access="ROLE_ANONYMOUS" /> 
     <intercept-url 
      pattern="/registered/*" 
      access="ROLE_USER" /> 
      <intercept-url 
      pattern="/*" 
      access="ROLE_ANONYMOUS" /> 
     <form-login 
      login-processing-url="/j_spring_security_check.html" 
      login-page="/auth/login.html" 
      default-target-url="/home.html" 
      authentication-failure-url="/login.html" /> 
     <logout invalidate-session="true" 
       logout-url="logout.html" 
       success-handler-ref="SuccessHandler"/> 
     <anonymous username="guest" granted-authority="ROLE_ANONYMOUS"/> 
     <remember-me user-service-ref="userManager" key="dfdfdfdff"/> 
     <custom-filter after="FORM_LOGIN_FILTER" ref="xmlAuthenticationFilter"/> 
    </http> 
    <!-- Configure the authentication provider --> 
    <authentication-manager alias="am"> 
     <authentication-provider user-service-ref="userManager"> 
       <password-encoder ref="passwordEncoder" /> 
     </authentication-provider> 
     <authentication-provider ref="xmlAuthenticationProvider" /> 
    </authentication-manager> 
</beans:beans> 

豆:

<?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:util="http://www.springframework.org/schema/util" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util-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/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    <context:annotation-config/> 
    <context:component-scan base-package="com.dc"/> 
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 
    <bean id="springContextHolder" class="SpringContextHolder" factory-method="getInstance" /> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="jpaVendorAdapter"> 
      <bean 
       class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="database" value="MYSQL" /> 
       <property name="showSql" value="true" /> 
      </bean> 
     </property> 
    </bean> 
    <bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
     <property name="url" value="jdbc:mysql://localhost:3306/webapp" /> 
     <property name="username" value="userid" /> 
     <property name="password" value="password" /> 
    </bean>  
    <bean id="transactionManager" 
     class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false"/> 
    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> 
     <property name="host" value="localhost"/> 
     <property name="port" value="25"/> 
    </bean> 
    <bean id="utilities" class="UtilitiesImpl"/> 
    <bean id="xmlAuthenticationFilter" class="com.dc.api.service.impl.XMLAuthenticationFilter"> 
     <property name="authenticationManager" ref="am" /> 
     <property name="utilities" ref="utilities"/> 
    </bean> 
    <bean id="xmlAuthenticationProvider" class="com.dc.api.service.impl.XMLAuthenticationProvider"> 
     <property name="userManager" ref="userManager"/> 
    </bean> 
    <bean id="DCLogoutSuccessHandler" class="LogoutSuccessHandler"/> 
</beans> 

的UserDetails实现:

import javax.inject.Inject; 

import org.springframework.dao.DataAccessException; 
import org.springframework.security.authentication.encoding.PasswordEncoder; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 
import org.springframework.stereotype.Service; 
import org.springframework.transaction.annotation.Isolation; 
import org.springframework.transaction.annotation.Propagation; 
import org.springframework.transaction.annotation.Transactional; 

import com.dc.api.dao.AuthorityDAO; 
import com.dc.api.dao.UserDAO; 
import com.dc.api.exception.ApiDataException; 
import com.dc.api.exception.EmailNotFoundException; 
import com.dc.api.helper.MailContentHelper; 
import com.dc.api.model.Users; 
import com.dc.api.model.vo.APIResponse; 
import com.dc.api.service.UserManager; 
import com.dc.api.service.Utilities; 

@Service("userManager") 
public class UserManagerImpl extends UserDetailsService { 
    @Inject 
    UserDAO userDAO; 
    @Inject 
    AuthorityDAO authorityDAO; 
    @Inject 
    PasswordEncoder passwordEncoder; 
    @Inject 
    Utilities utilities; 

    private void encodePassword(Users user) { 
     if (user.getPassword() == null && user.getRawPassword() != null) { 
      user.setPassword(passwordEncoder.encodePassword(user.getRawPassword(), null)); 
      user.setRawPassword(null); 
     } 
    } 

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { 
     Users user = null; 
     try { 
      user = userDAO.findByUsername(username); 
      if (user != null) { 

      } 
     } catch (DataAccessException ex) { 
      throw new UsernameNotFoundException("Invalid login", ex); 
     } 
     if (user == null) { 
      throw new UsernameNotFoundException("User not found."); 
     } 
     return user; 
    } 

    public Users getUser(String username) { 
     try { 
      return userDAO.findByUsername(username); 
     } catch (DataAccessException ex) { 
      // ignore 
      log.warn("Duplicate username: " + username); 
     } 
     return null; 
    } 

    public boolean isUsernameTaken(String username) { 
     try { 
      if (userDAO.findByUsername(username) == null) { 
       return false; 
      } else { 
       return true; 
      } 
     } catch (DataAccessException ex) { 
      // ignore 
      log.warn("Duplicate username: " + username); 
     } 
     return true; 
    } 

    public boolean isLoginValid(String username, String password) throws ApiDataException { 
     Users user = null; 
     try { 
      user = userDAO.findByUsername(username); 
     } catch (DataAccessException ex) { 
      throw new ApiDataException("Data Access Exception while verifying login"); 
     } 
     if (user == null) { 
      return false; 
     } 
     if (passwordEncoder.isPasswordValid(user.getPassword(), password, null)) { 
      return true; 
     } 
     return false; 
    } 

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) 
    public void saveUser(Users user) { 
     encodePassword(user); 
     userDAO.save(user); 
    } 

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) 
    public void updateUser(Users user) { 
     encodePassword(user); 
     userDAO.update(user); 
    } 

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) 
    public void resetPassword(String username, MailContentHelper mailContentHelper) { 
     String newPassword = utilities.generateSecret(8); 
     this.changePassword(username, newPassword, mailContentHelper); 
    } 

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) 
    public void changePassword(String username, String password, MailContentHelper mailContentHelper) { 
     Users user = userDAO.findByUsername(username); 
     user.setPassword(null); 
     user.setRawPassword(password); 
     encodePassword(user); 
     userDAO.update(user); 
     String firstName = user.getFirstName(); 
     firstName = (firstName == null) ? user.getUsername() : firstName; 
     //SimpleMailMessage message = mailContentHelper.retrieveContent(new Object[]{firstName, password, user.getEmail()}); 
     //utilities.sendMail(message); 
    } 
} 

的web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<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"> 
    <context-param> 
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name> 
    <param-value>/WEB-INF/facelet/dc.taglib.xml</param-value> 
    </context-param> 
    <context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
     WEB-INF/dc-context-api.xml 
     WEB-INF/dc-context-security.xml 
    </param-value> 
    </context-param> 
    <context-param> 
    <param-name>resteasy.resource.method-interceptors</param-name> 
    <param-value>org.jboss.resteasy.core.ResourceMethodSecurityInterceptor</param-value> 
    </context-param> 
    <context-param> 
    <param-name>resteasy.resources</param-name> 
    <param-value> 
     com.dc.web.actions.GlobalWebService</param-value> 
    </context-param> 
    <context-param> 
    <param-name>resteasy.servlet.mapping.prefix</param-name> 
    <param-value>/services/rest-api</param-value> 
    </context-param> 
    <context-param> 
    <param-name>resteasy.media.type.mappings</param-name> 
    <param-value>json : application/json, xml : application/xml</param-value> 
    </context-param> 
    <context-param> 
    <param-name>resteasy.resources</param-name> 
    <param-value> 
      com.WebService 
     </param-value> 
    </context-param> 
    <context-param> 
    <param-name>primefaces.THEME</param-name> 
    <param-value>none</param-value> 
    </context-param> 
    <context-param> 
     <param-name>log4jConfigLocation</param-name> 
     <param-value>/WEB-INF/log4j.properties</param-value> 
    </context-param> 
    <context-param> 
     <param-name>log4jRefreshInterval</param-name> 
     <param-value>1000</param-value> 
    </context-param> 
    <context-param> 
     <param-name>primefaces.PRIVATE_CAPTCHA_KEY</param-name> 
     <param-value>6LeL-MISAAAAAG6k07ch22oy-mxXBUi1MXKmrWiD</param-value> 
    </context-param> 
    <context-param> 
     <param-name>primefaces.PUBLIC_CAPTCHA_KEY</param-name> 
     <param-value>6LeL-MISAAAAAPTK5lYI9tK0SWWY2BqC2Hun7sH3</param-value> 
    </context-param> 
    <filter> 
    <filter-name>PrimeFaces FileUpload Filter</filter-name> 
     <filter-class>org.primefaces.webapp.filter.FileUploadFilter </filter-class> 
     <init-param> 
      <param-name>thresholdSize</param-name> <param-value>51200</param-value> 
     </init-param> 
     <init-param> 
      <param-name>uploadDirectory</param-name> 
      <param-value>url/upload</param-value> 
     </init-param> 
    </filter> 
    <filter-mapping> 
    <filter-name>PrimeFaces FileUpload Filter</filter-name> 
    <servlet-name>Faces Servlet</servlet-name> 
    </filter-mapping> 
    <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>*.html</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
    <dispatcher>REQUEST</dispatcher> 
    </filter-mapping> 
    <filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>*.xhtml</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
    <dispatcher>REQUEST</dispatcher> 
    </filter-mapping> 
    <filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/dc_security_check</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
    <dispatcher>REQUEST</dispatcher> 
    </filter-mapping> 
    <listener> 
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> 
    </listener> 
    <listener> 
    <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class> 
    </listener> 
    <listener> 
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
    </listener> 
    <listener> 
     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> 
    </listener> 
    <servlet> 
    <servlet-name>Resteasy</servlet-name> 
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> 
    </servlet> 
    <servlet> 
    <servlet-name>Faces Servlet</servlet-name> 
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>Resteasy</servlet-name> 
    <url-pattern>api/*</url-pattern> 
    </servlet-mapping> 
    <servlet-mapping> 
    <servlet-name>Faces Servlet</servlet-name> 
    <url-pattern>*.html</url-pattern> 
    </servlet-mapping> 
    <session-config> 
    <session-timeout>30</session-timeout> 
    </session-config> 
    <welcome-file-list> 
    <welcome-file>index.jsp</welcome-file> 
    <welcome-file>index.html</welcome-file> 
    </welcome-file-list> 
    <login-config> 
    <auth-method>BASIC</auth-method> 
    </login-config> 
</web-app> 

回答

3

它将您提交的密码与您的UserDetailsService返回的UserDetails对象返回的密码进行比较。如果您需要更多帮助,请发布您的配置和UserDetailsService

编辑:谢谢你的信息。它完全符合你的猜测。该ProviderManager(这是默认情况下使用)在其JavaDoc中的情况如下:

如果后续提供商成功 认证请求,早前 认证的例外是 忽视,并且成功 认证将被使用。

所以你的问题是后一个提供者“否决”第一个决定。

+0

感谢您的帮助,我已经添加了我的配置和impl ...我有一个基于表单的登录和自定义过滤器也。我想知道它可能会失败我的表单登录并转到不需要密码的自定义表单。 – c12 2011-03-31 01:19:05

相关问题