我尝试在Google上搜索,但我找不到任何好的示例,其中使用数据库检查用户名和密码以进行身份验证。
换句话说,如何使用Spring和Hibernate创建一个简单的登录表单,其中使用数据库检查凭据。
更新
Cam有没有人想出一个简单的例子,我可以看到流程如何以及输入数据如何传递给hibernate?
答案 0 :(得分:27)
首先,您应该定义此文件WEB-INF/spring/serurity-context.xml
:
<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-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
<http auto-config="true" />
<beans:bean id="myUserService" class="org.my.UserService" />
<authentication-provider user-service-ref="myUserService" />
</beans:beans>
现在您应该创建org.my.UserService
类并实现接口org.springframework.security.core.userdetails.UserDetailsService
。该界面有一种方法:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, org.springframework.dao.DataAccessException
在此方法中,您可以使用Hibernate以按用户名加载用户。如果用户不存在 - 只需抛出UsernameNotFoundException,否则返回新的初始化UserDetails实例(在那里你可以提供很多东西,比如用户角色,帐号到期日等等。)
现在来web.xml
:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>My Webapp</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*-context.xml
</param-value>
</context-param>
<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>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
如果您有任何问题或出现问题,请随时询问:)
PS:因此,使用UserDetailsService,您无需检查用户帐户是否处于活动状态等密码。您只需提供有关提供的userName
用户的弹簧安全信息,框架将验证用户自身。例如,如果您使用MD5对密码进行编码,则可以使用password-encoder
,如下所示:
<beans:bean id="myUserService" class="org.my.UserService" />
<authentication-provider user-service-ref="myUserService">
<password-encoder hash="md5"/>
</authentication-provider>
现在我们将更深入地探讨UserService
- 我的(简化)现实世界的例子。
UserService
上课:
import org.my_company.my_app.domain.User
public class UserService implements UserDetailsService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
// load user
User user = userDao.getUser(username);
if (user != null) {
// convert roles
List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
for (Privilege p : user.getPrivileges()) {
roles.add(new GrantedAuthorityImpl(p.getName()));
}
// initialize user
SecurityUser securityUser = new SecurityUser(
user.getUsername(),
user.getLdapAuth() ? getLdapPassword(user.getUsername()) : user.getPassword(),
user.getStatus() != User.Status.NOT_COMMITED, user.getStatus() != User.Status.BLOCKED, true, true,
roles.toArray(new GrantedAuthority[0])
);
securityUser.setUser(user);
return securityUser;
} else {
throw new UsernameNotFoundException("No user with username '" + username + "' found!");
}
}
}
现在SecurityUser
:
import org.my_company.my_app.domain.User
public class SecurityUser extends org.springframework.security.core.userdetails.User {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public SecurityUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) throws IllegalArgumentException {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
}
最后UserDao
:
import org.my_company.my_app.domain.User
public class UserDao extends HibernateDaoSupport {
public User getUser(String username) {
List users = getHibernateTemplate().find("from User where username = ?", username);
return users == null || users.size() <= 0 ? null : (User) users.get(0);
}
}
正如您所见,我在这里使用了HibernateTemplate
。
答案 1 :(得分:5)
您可以在“Easy Angle”的帖子中看到基本的xml配置。他提到的“myUserService”部分是一个实现“UserDetailService”的bean 那个基本上只有一种方法可以实现,如下所示
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException
如果你使用Spring,那么你可能会有一个Bean来处理对用户表的访问。您可以注入该类以检索用户详细信息,例如:
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException {
UserTable user = userbean.getUserbyName(name);
if (user == null) {
throw new UsernameNotFoundException("User " + name + " not found!");
}
Collection<GrantedAuthority> auth = getAuthorities(user.getAuthorities());
return new User(user.getName(), user.getPassword(), true, true, true, true, auth);
}
现在,在身份验证bean中,您只需要注入此bean并向其询问UserDetails。在那里,您可以使用它来检查凭据是否正确,如果是这样,请使用所需信息填充SecurityContext以便登录。
@Override
public Boolean authenticate(String username, String password) {
UserDetails userdetail = null;
try {
userdetail = myUserService.loadUserByUsername(username);
} catch (UsernameNotFoundException e) {
return false;
} catch (DataAccessException e) {
return false;
}
if (!myUserService.encodePassword(password).equals(userdetail.getPassword())) {
return false;
}
Authentication auth = new UsernamePasswordAuthenticationToken(userdetail.getUsername(), userdetail.getPassword(),
userdetail.getAuthorities());
SecurityContext sc = new SecurityContextImpl();
ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
attr.getRequest().getSession().setAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY, userdetail.getUsername());
sc.setAuthentication(auth);
SecurityContextHolder.setContext(sc);
return true;
}
当然这是真实版本的简化版本。在说用户进行身份验证之前,您必须执行更多检查(例如SQLInjection)
答案 2 :(得分:3)
App-fuse将为您提供一个完整的工作示例:http://appfuse.org/display/APF/AppFuse+QuickStart
如果您安装了maven,只需运行:
mvn archetype:generate -B -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-light-spring-security-archetype -DarchetypeVersion=2.1.0-M2 -DgroupId=com.mycompany -DartifactId=myproject
这将生成一个带有spring mvc,spring security和hibernate的appfuse light项目。
答案 3 :(得分:1)
如果您使用的是可以使用JDBC访问的数据库,则无需创建自定义身份验证提供程序。身份验证提供程序已允许您直接查询数据库。它将所需的代码减少到9行XML而不是多个类。
我在这里用代码示例回答了这个问题:Spring Security 3 database authentication with Hibernate