在本教程中,我们将向您展示如何在Spring Security XML配置示例中集成Hibernate 4。
注意
对于注释版本,请阅读此Spring Security + Hibernate注释示例 。
使用的技术:
- 春天3.2.8。发布
- Spring Security 3.2.3发布
- 休眠4.2.11.Final
- MySQL服务器5.6
- JDK 1.6
- Maven 3
- Eclipse 4.3
快速笔记
- 使用
hibernate4.LocalSessionFactoryBean
创建一个会话工厂 - 将会话工厂注入UserDao
- 要与Spring Security集成,请创建一个实现
UserDetailsService
接口的类,并使用UserDao加载User - 必须声明事务管理器,否则Hibernate在Spring中将无法工作
1.项目目录
最终项目目录结构。
2.项目依赖性
POM文件中项目的依赖项列表。
<properties>
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
<jstl.version>1.2</jstl.version>
<mysql.connector.version>5.1.30</mysql.connector.version>
<logback.version>1.1.2</logback.version>
<slf4j.version>1.7.6</slf4j.version>
<hibernate.version>4.2.11.Final</hibernate.version>
<dbcp.version>1.4</dbcp.version>
<servletapi.version>2.5</servletapi.version>
</properties>
<dependencies>
<!-- database pool -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${dbcp.version}</version>
</dependency>
<!-- Hibernate ORM -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring + aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- ORM integration, e.g Hibernate -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- Spring Security JSP Taglib -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- jstl for jsp page -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- MySql Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<!-- logging, slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servletapi.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
3.用户表
创建表以存储用户和用户角色的SQL脚本。
CREATE TABLE users (
username VARCHAR(45) NOT NULL ,
password VARCHAR(60) NOT NULL ,
enabled TINYINT NOT NULL DEFAULT 1 ,
PRIMARY KEY (username));
CREATE TABLE user_roles (
user_role_id int(11) NOT NULL AUTO_INCREMENT,
username varchar(45) NOT NULL,
role varchar(45) NOT NULL,
PRIMARY KEY (user_role_id),
UNIQUE KEY uni_username_role (role,username),
KEY fk_username_idx (username),
CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username));
INSERT INTO users(username,password,enabled)
VALUES ('mkyong','$2a$10$04TVADrR6/SPLBjsK0N30.Jf5fNjBugSACeGv1S69dZALR7lSov0y', true);
INSERT INTO users(username,password,enabled)
VALUES ('alex','$2a$10$04TVADrR6/SPLBjsK0N30.Jf5fNjBugSACeGv1S69dZALR7lSov0y', true);
INSERT INTO user_roles (username, role)
VALUES ('mkyong', 'ROLE_USER');
INSERT INTO user_roles (username, role)
VALUES ('mkyong', 'ROLE_ADMIN');
INSERT INTO user_roles (username, role)
VALUES ('alex', 'ROLE_USER');
4.用户模型+ Hibernate XML映射
模型类及其XML映射文件。
package com.mkyong.users.model;
import java.util.HashSet;
import java.util.Set;
public class User {
private String username;
private String password;
private boolean enabled;
private Set<UserRole> userRole = new HashSet<UserRole>(0);
//getter and setter methods
}
package com.mkyong.users.model;
public class UserRole{
private Integer userRoleId;
private User user;
private String role;
//getter and setter methods
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.mkyong.users.model.User" table="users" catalog="test">
<id name="username" type="string">
<column name="username" length="45" />
<generator class="assigned" />
</id>
<property name="password" type="string">
<column name="password" length="60" not-null="true" />
</property>
<property name="enabled" type="boolean">
<column name="enabled" not-null="true" />
</property>
<set name="userRole" table="user_roles" inverse="true" lazy="true" fetch="select">
<key>
<column name="username" length="45" not-null="true" />
</key>
<one-to-many class="com.mkyong.users.model.UserRole" />
</set>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.mkyong.users.model.UserRole" table="user_roles" catalog="test">
<id name="userRoleId" type="java.lang.Integer">
<column name="user_role_id" />
<generator class="identity" />
</id>
<many-to-one name="user" class="com.mkyong.users.model.User" fetch="select">
<column name="username" length="45" not-null="true" />
</many-to-one>
<property name="role" type="string">
<column name="role" length="45" not-null="true" />
</property>
</class>
</hibernate-mapping>
5. DAO类
创建一个UserDao
类,以通过Hibernate从数据库中加载用户。
package com.mkyong.users.dao;
import com.mkyong.users.model.User;
public interface UserDao {
User findByUserName(String username);
}
package com.mkyong.users.dao;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.SessionFactory;
import com.mkyong.users.model.User;
public class UserDaoImpl implements UserDao {
private SessionFactory sessionFactory;
@SuppressWarnings("unchecked")
public User findByUserName(String username) {
List<User> users = new ArrayList<User>();
users = getSessionFactory().getCurrentSession()
.createQuery("from User where username=?")
.setParameter(0, username).list();
if (users.size() > 0) {
return users.get(0);
} else {
return null;
}
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
6. UserDetailsService
创建一个自定义UserDetailsService
,从UserDao
加载用户,然后构建用户的权限。
注意
示例是从此Spring的JdbcDaoImpl中引用的
package com.mkyong.users.service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.mkyong.users.dao.UserDao;
import com.mkyong.users.model.UserRole;
public class MyUserDetailsService implements UserDetailsService {
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(final String username)
throws UsernameNotFoundException {
com.mkyong.users.model.User user = userDao.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());
return buildUserForAuthentication(user, authorities);
}
// Converts com.mkyong.users.model.User user to
// org.springframework.security.core.userdetails.User
private User buildUserForAuthentication(com.mkyong.users.model.User user,
List<GrantedAuthority> authorities) {
return new User(user.getUsername(),
user.getPassword(), user.isEnabled(),
true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
7. Spring Security 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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- enable use-expressions -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login
login-page="/login"
default-target-url="/welcome"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf />
</http>
<authentication-manager>
<authentication-provider user-service-ref="myUserDetailsService" >
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
</beans:beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- MySQL data source -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>orm/Users.hbm.xml</value>
<value>orm/UserRoles.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQL5Dialect
</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="userDao" class="com.mkyong.users.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="myUserDetailsService"
class="com.mkyong.users.service.MyUserDetailsService">
<property name="userDao" ref="userDao" />
</bean>
<!-- MUST have transaction manager, using aop and aspects -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="userServicePointCut"
expression="execution(* com.mkyong.users.service.*Service.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut" />
</aop:config>
</beans>
做完了
注意
那些JSP,web.xml和控制器文件被省略,这是一个标准的代码,如果您对此感兴趣,请在文章末尾下载完整的源代码。
8.项目演示
以下视频演示用于使用JDBC教程登录Spring Security数据库 。 由于本教程生成了相同的输出,但是使用了Hibernate来加载User,因此可以重用视频演示。
8.1进入密码保护页面:http:// localhost:8080 / spring-security-hibernate / admin,显示登录页面。
8.2输入用户“ mkyong”和密码“ 123456”。
8.3尝试使用用户“ alex”和密码“ 123456”访问/admin
页面,将显示403页面。
下载源代码
下载它– spring-security-hibernate.zip (30 KB)
参考文献
- SpringORM –休眠
- Spring Hibernate4 LocalSessionFactoryBean JavaDoc
- Spring Hibernate3 LocalSessionFactoryBean JavaDoc
- Spring交易管理
- Hibernate ORM文档
- 使用JDBC和数据库使用Spring Security Form登录
- Hibernate:找不到当前线程的会话
翻译自: https://mkyong.com/spring-security/spring-security-hibernate-xml-example/