我正在实现spring security 3.0.5,并在我的基于表单的登录中扩展了Spring UserDetailsService。目前我的登录表单只验证用户名而不是密码。 spring security在哪里验证发布到/ j_spring_security_check的密码?
安全配置:
<?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>
答案 0 :(得分:3)
它会将您提交的密码与UserDetails
返回的UserDetailsService
对象返回的密码进行比较。如果您需要更多帮助,请发布您的配置和UserDetailsService
。
ProviderManager
(默认情况下使用)在其JavaDoc中具有以下内容:
如果后续提供商成功 验证请求,更早 身份验证例外是 无视和成功 将使用身份验证。
所以你的问题是后一个提供者“推翻”第一个决定。