这篇主要的内容是
通过自定义Spring Security的默认实现来进行用户和权限的管理
通过第六篇和第七篇的铺垫 现在开始这篇的实验,第六篇中我们可以自定义自己的用户和权限表结构了
但是 我们必须确保我们的SQL 语句返回的列与Spring Security 所期待的一样 是因为我们仍然使用的是
SpringSecurity的默认实现,那么这篇我们自己实现SpirngSecurity对用户和权限的管理.
学习资料 来自 这个大哥的博客 http://downpour.iteye.com/blog/319965
准备工作:
在此之前我们自定义的用户表和权限表 是一个多对多的关系 通过中间表进行关联.
那么这里我们在程序里要怎样进行 映射 当然可以使用MyEclipses的反向工程,
这里我们手动的创建用户类和权限类之间的单向多对多关联
annotation 注解方式 完成映射. 使用hibernate 帮助我们方便进行数据库操作
1.创建User类(用户类)与数据库tb_users表 对应
package zyk.entity;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Proxy;
@SuppressWarnings("serial")
@Entity
@Table(name = "tb_users")
@Proxy(lazy = false)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User implements Serializable {
private int id;
private String name;
private String pwd;
private String enabled;
private Set<Role> roles;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "c_username")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "c_password")
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Column(name = "c_enabled")
public String getEnabled() {
return enabled;
}
public void setEnabled(String enabled) {
this.enabled = enabled;
}
@ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER)
@JoinTable(name = "tb_user_role", joinColumns = @JoinColumn(name = "c_user_id"), inverseJoinColumns = @JoinColumn(name = "c_role_id"))
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
2.创建Role类(权限类)与数据库tb_role表 对应
package zyk.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
/**
* 权限类
* */
@SuppressWarnings("serial")
@Entity
@Table(name = "tb_role")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Role implements Serializable {
private int id;
private String authority;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "c_authority")
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
}
单向的多对多关联关系建立OK。。
Spring Security的用户和权限的管理的具体实现
1.分别实现接口 GrantedAuthority (权限),UserDetails(用户详细信息) ,UserDetailsService(用户信息管理)
1.1 创建MyGrantedAuthority
package zyk.security;
import org.springframework.security.core.GrantedAuthority;
/**
* 权限类.
* */
public class MyGrantedAuthority implements GrantedAuthority {
private static final long serialVersionUID = 1L;
private String authority;
public MyGrantedAuthority() {
}
public MyGrantedAuthority(String authority) {
this.authority = authority;
}
//返回权限字串
public String getAuthority() {
return this.authority;
}
}
1.2 创建MyUserDetails
package zyk.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import zyk.entity.Role;
import zyk.entity.User;
/**
* 用户信息详细类
* */
public class MyUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
public MyUserDetails() {
}
public MyUserDetails(User user) {
this.user = user;
}
private User user;
//获得该用户的所有权限
public Collection<GrantedAuthority> getAuthorities() {
Set<Role> roles = this.user.getRoles();
List<GrantedAuthority> grantedAuthoritys = new ArrayList<GrantedAuthority>(
roles.size());
for (Role role : roles) {
GrantedAuthority grantedAuthority = new MyGrantedAuthority(
role.getAuthority());
grantedAuthoritys.add(grantedAuthority);
}
return grantedAuthoritys;
}
public String getPassword() {
return this.user.getPwd();
}
public String getUsername() {
return this.user.getName();
}
public boolean isAccountNonExpired() {
return true;
}
public boolean isAccountNonLocked() {
return true;
}
public boolean isCredentialsNonExpired() {
return true;
}
public boolean isEnabled() {
return this.user.getEnabled().equals("1") == true ? true : false;
}
}
1.3 创建 MyUserDetailsService
package zyk.security;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import zyk.entity.User;
/**
* 用户信息管理类
* */
@Component("userDetailsService")
public class MyUserDetailsService extends HibernateDaoSupport implements
UserDetailsService {
@Autowired
public void init(SessionFactory sessionFactory) {
super.setSessionFactory(sessionFactory);
}
//这里load用户信息 登录时进入这里.
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
String queryString = "from User u where u.name=?";
@SuppressWarnings("unchecked")
List<User> users = this.getHibernateTemplate().find(queryString,
username);
if (users.size() == 0) {
throw new UsernameNotFoundException("User " + username + "不存在!");
}
User user = users.get(0);
UserDetails userDetails = new MyUserDetails(user);
return userDetails;
}
}
1.4 进行配置 (applicationContext.xml)和 (applicationContext-security.xml) 配置信息
已经贴到第7篇上面了 这是annotation 的实现方式 注释部分是XML 方式的配置.请参考.
这样就可以测试了 .