Spring Security使用Hibernate实现自定义UserDetails
首先,我们将在数据库中需要以下表格:
CREATE TABLE IF NOT EXISTS `mydb`.`security_role` (`id` INT(11) NOT NULL AUTO_INCREMENT ,`name` VARCHAR(50) NULL DEFAULT NULL ,PRIMARY KEY (`id`) )ENGINE = InnoDBAUTO_INCREMENT = 4DEFAULT CHARACTER SET = latin1;CREATE TABLE IF NOT EXISTS `mydb`.`user` (`id` INT(11) NOT NULL AUTO_INCREMENT ,`first_name` VARCHAR(45) NULL DEFAULT NULL ,`family_name` VARCHAR(45) NULL DEFAULT NULL ,`dob` DATE NULL DEFAULT NULL ,`password` VARCHAR(45) NOT NULL ,`username` VARCHAR(45) NOT NULL ,`confirm_password` VARCHAR(45) NOT NULL ,`active` TINYINT(1) NOT NULL ,PRIMARY KEY (`id`) ,UNIQUE INDEX `username` (`username` ASC) )ENGINE = InnoDBAUTO_INCREMENT = 9DEFAULT CHARACTER SET = latin1;CREATE TABLE IF NOT EXISTS `mydb`.`user_security_role` (`user_id` INT(11) NOT NULL ,`security_role_id` INT(11) NOT NULL ,PRIMARY KEY (`user_id`, `security_role_id`) ,INDEX `security_role_id` (`security_role_id` ASC) ,CONSTRAINT `user_security_role_ibfk_1`FOREIGN KEY (`user_id` )REFERENCES `mydb`.`user` (`id` ),CONSTRAINT `user_security_role_ibfk_2`FOREIGN KEY (`security_role_id` )REFERENCES `mydb`.`security_role` (`id` ))ENGINE = InnoDBDEFAULT CHARACTER SET = latin1;
显然,表用户将拥有用户,表security_role将拥有安全角色,而user_security_roles将拥有关联。 为了使实现尽可能简单,security_role表中的条目应始终以“ ROLE_”开头,否则我们将需要封装(本文将不涉及)。
因此,我们执行以下语句:
insert into security_role(name) values ('ROLE_admin');insert into security_role(name) values ('ROLE_Kennel_Owner');insert into security_role(name) values ('ROLE_User');insert into user (first_name,family_name,password,username,confirm_password,active)values ('ioannis','ntantis','123456','giannisapi','123456',1);insert into user_security_role (user_id,security_role_id) values (1,1);
因此,执行这些命令后,我们将得到以下内容:
三种不同的安全角色
一位用户名为“ giannisapi”的用户
我们已将角色“ ROLE_admin”赋予用户“ giannisapi”
现在,一切都已在数据库端完成,我们将移至Java端,看看需要做什么。
首先,我们将创建必要的DTO(有多种工具可以为您自动从数据库生成DTO):
package org.intan.pedigree.form;import java.io.Serializable;import java.util.Collection;import java.util.Date;import java.util.Set;import javax.persistence.Basic;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.JoinTable;import javax.persistence.ManyToMany;import javax.persistence.NamedQueries;import javax.persistence.NamedQuery;import javax.persistence.Table;import javax.persistence.Temporal;import javax.persistence.TemporalType;/**** @author intan*/@Entity@Table(name = 'user', catalog = 'mydb', schema = '')@NamedQueries({@NamedQuery(name = 'UserEntity.findAll', query = 'SELECT u FROM UserEntity u'),@NamedQuery(name = 'UserEntity.findById', query = 'SELECT u FROM UserEntity u WHERE u.id = :id'),@NamedQuery(name = 'UserEntity.findByFirstName', query = 'SELECT u FROM UserEntity u WHERE u.firstName = :firstName'),@NamedQuery(name = 'UserEntity.findByFamilyName', query = 'SELECT u FROM UserEntity u WHERE u.familyName = :familyName'),@NamedQuery(name = 'UserEntity.findByDob', query = 'SELECT u FROM UserEntity u WHERE u.dob = :dob'),@NamedQuery(name = 'UserEntity.findByPassword', query = 'SELECT u FROM UserEntity u WHERE u.password = :password'),@NamedQuery(name = 'UserEntity.findByUsername', query = 'SELECT u FROM UserEntity u WHERE u.username = :username'),@NamedQuery(name = 'UserEntity.findByConfirmPassword', query = 'SELECT u FROM UserEntity u WHERE u.confirmPassword = :confirmPassword'),@NamedQuery(name = 'UserEntity.findByActive', query = 'SELECT u FROM UserEntity u WHERE u.active = :active')})public class UserEntity implements Serializable {private static final long serialVersionUID = 1L;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Basic(optional = false)@Column(name = 'id')private Integer id;@Column(name = 'first_name')private String firstName;@Column(name = 'family_name')private String familyName;@Column(name = 'dob')@Temporal(TemporalType.DATE)private Date dob;@Basic(optional = false)@Column(name = 'password')private String password;@Basic(optional = false)@Column(name = 'username')private String username;@Basic(optional = false)@Column(name = 'confirm_password')private String confirmPassword;@Basic(optional = false)@Column(name = 'active')private boolean active;@JoinTable(name = 'user_security_role', joinColumns = {@JoinColumn(name = 'user_id', referencedColumnName = 'id')}, inverseJoinColumns = {@JoinColumn(name = 'security_role_id', referencedColumnName = 'id')})@ManyToManyprivate Set securityRoleCollection;public UserEntity() {}public UserEntity(Integer id) {this.id = id;}public UserEntity(Integer id, String password, String username, String confirmPassword, boolean active) {this.id = id;this.password = password;this.username = username;this.confirmPassword = confirmPassword;this.active = active;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getFamilyName() {return familyName;}public void setFamilyName(String familyName) {this.familyName = familyName;}public Date getDob() {return dob;}public void setDob(Date dob) {this.dob = dob;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getConfirmPassword() {return confirmPassword;}public void setConfirmPassword(String confirmPassword) {this.confirmPassword = confirmPassword;}public boolean getActive() {return active;}public void setActive(boolean active) {this.active = active;}public Set getSecurityRoleCollection() {return securityRoleCollection;}public void setSecurityRoleCollection(Set securityRoleCollection) {this.securityRoleCollection = securityRoleCollection;}@Overridepublic int hashCode() {int hash = 0;hash += (id != null ? id.hashCode() : 0);return hash;}@Overridepublic boolean equals(Object object) {// TODO: Warning - this method won't work in the case the id fields are not setif (!(object instanceof UserEntity)) {return false;}UserEntity other = (UserEntity) object;if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {return false;}return true;}@Overridepublic String toString() {return 'org.intan.pedigree.form.User[id=' + id + ']';}}
package org.intan.pedigree.form;import java.io.Serializable;import java.util.Collection;import javax.persistence.Basic;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.ManyToMany;import javax.persistence.NamedQueries;import javax.persistence.NamedQuery;import javax.persistence.Table;/**** @author intan*/@Entity@Table(name = 'security_role', catalog = 'mydb', schema = '')@NamedQueries({@NamedQuery(name = 'SecurityRoleEntity.findAll', query = 'SELECT s FROM SecurityRoleEntity s'),@NamedQuery(name = 'SecurityRoleEntity.findById', query = 'SELECT s FROM SecurityRoleEntity s WHERE s.id = :id'),@NamedQuery(name = 'SecurityRoleEntity.findByName', query = 'SELECT s FROM SecurityRoleEntity s WHERE s.name = :name')})public class SecurityRoleEntity implements Serializable {private static final long serialVersionUID = 1L;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Basic(optional = false)@Column(name = 'id')private Integer id;@Column(name = 'name')private String name;@ManyToMany(mappedBy = 'securityRoleCollection')private Collection userCollection;public SecurityRoleEntity() {}public SecurityRoleEntity(Integer id) {this.id = id;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Collection getUserCollection() {return userCollection;}public void setUserCollection(Collection userCollection) {this.userCollection = userCollection;}@Overridepublic int hashCode() {int hash = 0;hash += (id != null ? id.hashCode() : 0);return hash;}@Overridepublic boolean equals(Object object) {// TODO: Warning - this method won't work in the case the id fields are not setif (!(object instanceof SecurityRoleEntity)) {return false;}SecurityRoleEntity other = (SecurityRoleEntity) object;if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {return false;}return true;}@Overridepublic String toString() {return 'org.intan.pedigree.form.SecurityRole[id=' + id + ']';}}
现在我们已经有了DTO,让我们创建必要的DAO类:
package org.intan.pedigree.dao;import java.util.List;import java.util.Set;import org.hibernate.SessionFactory;import org.intan.pedigree.form.SecurityRoleEntity;import org.intan.pedigree.form.UserEntity;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;@Repositorypublic class UserEntityDAOImpl implements UserEntityDAO{@Autowiredprivate SessionFactory sessionFactory;public void addUser(UserEntity user) {try {sessionFactory.getCurrentSession().save(user);} catch (Exception e) {System.out.println(e);}}public UserEntity findByName(String username) {UserEntity user = (UserEntity) sessionFactory.getCurrentSession().createQuery('select u from UserEntity u where u.username = '' + username + ''').uniqueResult();return user;}public UserEntity getUserByID(Integer id) {UserEntity user = (UserEntity) sessionFactory.getCurrentSession().createQuery('select u from UserEntity u where id = '' + id + ''').uniqueResult();return user;}public String activateUser(Integer id) {String hql = 'update UserEntityset active = :active where id = :id';org.hibernate.Query query = sessionFactory.getCurrentSession().createQuery(hql);query.setString('active','Y');query.setInteger('id',id);int rowCount = query.executeUpdate();System.out.println('Rows affected: ' + rowCount);return '';}public String disableUser(Integer id) {String hql = 'update UserEntity set active = :active where id = :id';org.hibernate.Query query = sessionFactory.getCurrentSession().createQuery(hql);query.setInteger('active',0);query.setInteger('id',id);int rowCount = query.executeUpdate();System.out.println('Rows affected: ' + rowCount);return '';}public void updateUser(UserEntity user) {try {sessionFactory.getCurrentSession().update(user);} catch (Exception e) {System.out.println(e);}}public List listUser() {return sessionFactory.getCurrentSession().createQuery('from UserEntity').list();}public void removeUser(Integer id) {UserEntity user = (UserEntity) sessionFactory.getCurrentSession().load(UserEntity.class, id);if (null != user) {sessionFactory.getCurrentSession().delete(user);}}public Set getSecurityRolesForUsername(String username) {UserEntity user = (UserEntity) sessionFactory.getCurrentSession().createQuery('select u from UserEntity u where u.username = '' + username + ''').uniqueResult();if (user!= null) {Set roles = (Set) user.getSecurityRoleCollection();if (roles != null && roles.size() > 0) {return roles;}}return null;}}
package org.intan.pedigree.dao;import java.util.List;import org.hibernate.Criteria;import org.hibernate.SessionFactory;import org.hibernate.criterion.Restrictions;import org.intan.pedigree.form.Country;import org.intan.pedigree.form.Kennel;import org.intan.pedigree.form.SecurityRoleEntity;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;@Repositorypublic class SecurityRoleEntityDAOImpl implements SecurityRoleEntityDAO{@Autowiredprivate SessionFactory sessionFactory;public void addSecurityRoleEntity(SecurityRoleEntity securityRoleEntity) {try {sessionFactory.getCurrentSession().save(securityRoleEntity);} catch (Exception e) {System.out.println(e);}}public List listSecurityRoleEntity() {Criteria criteria = sessionFactory.getCurrentSession().createCriteria(SecurityRoleEntity.class);criteria.add(Restrictions.ne('name','ROLE_ADMIN' ));return criteria.list();}public SecurityRoleEntity getSecurityRoleEntityById(Integer id) {Criteria criteria = sessionFactory.getCurrentSession().createCriteria(SecurityRoleEntity.class);criteria.add(Restrictions.eq('id',id));return (SecurityRoleEntity) criteria.uniqueResult();}public void removeSecurityRoleEntity(Integer id) {SecurityRoleEntity securityRoleEntity = (SecurityRoleEntity) sessionFactory.getCurrentSession().load(SecurityRoleEntity.class, id);if (null != securityRoleEntity) {sessionFactory.getCurrentSession().delete(securityRoleEntity);}}}
现在,我们将为上述DAO创建服务层。
package org.intan.pedigree.service;import java.util.List;import org.intan.pedigree.dao.SecurityRoleEntityDAO;import org.intan.pedigree.form.SecurityRoleEntity;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Servicepublic class SecurityRoleEntityServiceImpl implements SecurityRoleEntityService{@Autowiredprivate SecurityRoleEntityDAO securityRoleEntityDAO;@Transactionalpublic void addSecurityRoleEntity(SecurityRoleEntity securityRoleEntity) {securityRoleEntityDAO.addSecurityRoleEntity(securityRoleEntity);}@Transactionalpublic List listSecurityRoleEntity() {return securityRoleEntityDAO.listSecurityRoleEntity();}@Transactionalpublic void removeSecurityRoleEntity(Integer id) {securityRoleEntityDAO.removeSecurityRoleEntity(id);}@Transactionalpublic SecurityRoleEntity getSecurityRoleEntityById(Integer id) {return securityRoleEntityDAO.getSecurityRoleEntityById( id);}}
在下面的UserDetails的服务层中,请注意它是从org.springframework.security.core.userdetails.UserDetailsService实现UserDetailsService的。
package org.intan.pedigree.service;import org.intan.pedigree.dao.UserEntityDAO;import org.intan.pedigree.dao.UserEntityDAO;import org.intan.pedigree.form.UserEntity;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.dao.DataAccessException;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;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;@Service('userDetailsService')public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserEntityDAO dao;@Autowiredprivate Assembler assembler;@Transactional(readOnly = true)public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException, DataAccessException {UserDetails userDetails = null;UserEntity userEntity = dao.findByName(username);if (userEntity == null)throw new UsernameNotFoundException('user not found');return assembler.buildUserFromUserEntity(userEntity);}}
您还在上面看到,loadUserByUsername方法返回assembler.buildUserFromUserEntity的结果。 简而言之,汇编程序的这种方法是从给定的UserEntity DTO构造一个org.springframework.security.core.userdetails.User对象。 下面给出了Assembler类的代码:
package org.intan.pedigree.service;import java.util.ArrayList;import java.util.Collection;import org.intan.pedigree.form.SecurityRoleEntity;import org.intan.pedigree.form.UserEntity;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.GrantedAuthorityImpl;import org.springframework.security.core.userdetails.User;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Service('assembler')public class Assembler {@Transactional(readOnly = true)User buildUserFromUserEntity(UserEntity userEntity) {String username = userEntity.getUsername();String password = userEntity.getPassword();boolean enabled = userEntity.getActive();boolean accountNonExpired = userEntity.getActive();boolean credentialsNonExpired = userEntity.getActive();boolean accountNonLocked = userEntity.getActive();Collection authorities = new ArrayList();for (SecurityRoleEntity role : userEntity.getSecurityRoleCollection()) {authorities.add(new GrantedAuthorityImpl(role.getName()));}User user = new User(username, password, enabled,accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);return user;}}
现在剩下要做的唯一事情就是定义applicationContext-Security.xml中必需的内容。 为此,创建一个具有以下内容的名为“ applicationContext-Security.xml”的新xml文件:
<?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:xsi='http://www.w3.org/2001/XMLSchema-instance'xmlns:context='http://www.springframework.org/schema/context'xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd'><beans:bean id='userDetailsService' class='org.intan.pedigree.service.UserDetailsServiceImpl'></beans:bean><context:component-scan base-package='org.intan.pedigree' /><http auto-config='true'><intercept-url pattern='/admin/**' access='ROLE_ADMIN' /><intercept-url pattern='/user/**' access='ROLE_REGISTERED_USER' /><intercept-url pattern='/kennel/**' access='ROLE_KENNEL_OWNER' /><!-- <security:intercept-url pattern='/login.jsp' access='IS_AUTHENTICATED_ANONYMOUSLY' /> --></http><beans:bean id='daoAuthenticationProvider'class='org.springframework.security.authentication.dao.DaoAuthenticationProvider'><beans:property name='userDetailsService' ref='userDetailsService' /></beans:bean><beans:bean id='authenticationManager'class='org.springframework.security.authentication.ProviderManager'><beans:property name='providers'><beans:list><beans:ref local='daoAuthenticationProvider' /></beans:list></beans:property></beans:bean><authentication-manager><authentication-provider user-service-ref='userDetailsService'><password-encoder hash='plaintext' /></authentication-provider></authentication-manager></beans:beans>
在您的web.xml中放入以下代码,以加载applicationContext-security.xml文件。
<context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext-hibernate.xml/WEB-INF/applicationContext-security.xml</param-value></context-param>
最后,请原谅任何输入错误等,因为此代码只是从我完成的个人工作中复制和粘贴的内容,如果某些操作不起作用,请提出问题,我们将非常乐意为您提供帮助。
参考: Spring 3,Spring Security在Giannisapi博客上与我们的JCG合作伙伴 Ioannis Dadis 一起使用Hibernate实现自定义用户 详细信息 。
翻译自: https://www.javacodegeeks.com/2012/08/spring-security-implementing-custom.html
Spring Security使用Hibernate实现自定义UserDetails相关推荐
- 实现userdetails_Spring Security使用Hibernate实现自定义UserDetails
实现userdetails 大多数时候,我们将要在Web应用程序中配置我们自己的安全访问角色. 这在Spring Security中很容易实现. 在本文中,我们将看到最简单的方法. 首先,我们将在数据 ...
- Spring Security 实战干货:自定义配置类入口 WebSecurityConfigurerAdapter
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 1. 前言 今天我们要进一步的的学习如何自定义配置 Sp ...
- Spring Security 实战干货:自定义异常处理
Spring Security 实战干货:自定义异常处理 转自:https://www.cnblogs.com/felordcn/p/12142514.html 文章目录 1. 前言 2. Sprin ...
- Spring Security 进阶干货:自定义配置类入口WebSecurityConfigurerAdapter
1. 前言 今天我们要进一步的的学习如何自定义配置 Spring Security 我们已经多次提到了 WebSecurityConfigurerAdapter ,而且我们知道 Spring Boot ...
- 看清spring security 认证流程,自定义认证方式
一.文献参考 Spring Security认证与授权的原理(源码分析,超详细)_Zystem-CSDN博客_springsecurity认证原理 spring security为什么这么复杂? - ...
- 【Spring Security】五、自定义过滤器
在之前的几篇security教程中,资源和所对应的权限都是在xml中进行配置的,也就在http标签中配置intercept-url,试想要是配置的对象不多,那还好,但是平常实际开发中都往往是非常多的资 ...
- Spring Security——SessionManagement中InvalidSessionStrategy自定义——简单跳过Fitter过滤刷新Session
需求分析 解决方案 创建一个新的Session,并且重定向到原请求地址. /*** @author ShenTuZhiGang* @version 1.0.0* @date 2021-02-16 21 ...
- Spring Security 实战:实现自定义退出登录
1. 前言 上一篇对 Spring Security 所有内置的 Filter 进行了介绍.今天我们来实战如何安全退出应用程序. 2. 我们使用 Spring Security 登录后都做了什么 这个 ...
- Spring MVC 4 + Spring Security 4 + Hibernate +JPA实战
最近花了有三个星期把spring实战学了遍,同时也把maven,git,Hibernate给用上了,确实比较锻炼手.登陆,注册(我前端不是很好)是网上找得模版,(提前说下界面做的很挫,是用来练手的,还 ...
最新文章
- 微软nni_实践空间站 | 为微软官方开源项目贡献代码,你准备好了吗?
- Kubernetes安全之鉴权
- 服务器管理器运行添加角色向导,Windows Server 2008 服务器角色的添加与管理
- 【Tomcat】Tomcat配置与优化(内存、并发、管理)【自己配置】
- centos linux 内核升级,Centos系统的升级及Linux 内核升级
- Background-size完美兼容IE
- 从hadoop-0.20.2升级到hadoop-1.0.3
- 突然!华为P30 Pro真机上手视频曝光:屏幕指纹解锁秒开
- UIViewController的生命周期
- 7个免费的在线音频编辑网站推荐
- matlab 动态优化,基于Matlab的测控系统动态性能优化与仿真
- 港科夜闻|香港科大(广州)熊辉教授获委任为协理副校长(知识转移)
- Java 中代码优化的 30 个小技巧(下)
- 《菜菜的机器学习sklearn课堂(2),Java编程百度云
- Hive常用库表操作及知识汇总
- 文件拖到ads快捷方式打不开
- python三大器_python三大器(装饰器/生成器/迭代器)
- 【线程基础】多个线程,顺序输出
- 2012年全国通信行业职业水平考试结束
- 2021中行校招面试
热门文章
- maven项目 报错 java.lang.ClassNotFoundException: org.springframework.web.filter.HiddenHttpMethodFilter
- kafka mirror_SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战
- neo4j 关系属性_Neo4j:特定关系与一般关系+属性
- java 程序增加 防盗_防盗Java EE –保护Java EE企业应用程序的安全
- jax-rs jax-ws_JAX-RS 2.x与Spring MVC:返回对象列表的XML表示
- spring 项目集成配置_Spring重试–与项目集成的方式
- jsr303自定义验证_JSR 310新日期/时间API的自定义JSR 303 Bean验证约束
- javabeans_(单元测试)JavaBeans的技巧
- java字节码_好的,每个接触Java字节码的人
- 带有Spring Cloud Config和JHipster的Java微服务