Spring Security默认提供的表结构太过简单了,其实就算默认提供的表结构很复杂,也无法满足所有企业内部对用户信息和权限信息管理的要求。基本上每个企业内部都有一套自己的用户信息管理结构,同时也会有一套对应的权限信息体系,如何让Spring Security在这些已有的数据结构之上运行呢?
假设我们实际使用的表结构如下所示:
-- 角色 create table role( id bigint, name varchar(50), descn varchar(200) ); alter table role add constraint pk_role primary key(id); alter table role alter column id bigint generated by default as identity(start with 1); -- 用户 create table user( id bigint, username varchar(50), password varchar(50), status integer, descn varchar(200) ); alter table user add constraint pk_user primary key(id); alter table user alter column id bigint generated by default as identity(start with 1); -- 用户角色连接表 create table user_role( user_id bigint, role_id bigint ); alter table user_role add constraint pk_user_role primary key(user_id, role_id); alter table user_role add constraint fk_user_role_user foreign key(user_id) references user(id); alter table user_role add constraint fk_user_role_role foreign key(role_id) references role(id);
上述共有三张表,其中user用户表,role角色表为保存用户权限数据的主表,user_role为关联表。user用户表,role角色表之间为多对多关系,就是说一个用户可以有多个角色。ER图如下所示:
创建两个用户,admin和user。admin用户拥有“管理员”角色,user用户拥有“用户”角色。
insert into user(id,username,password,status,descn) values(1,'admin','admin',1,'管理员'); insert into user(id,username,password,status,descn) values(2,'user','user',1,'用户'); insert into role(id,name,descn) values(1,'ROLE_ADMIN','管理员角色'); insert into role(id,name,descn) values(2,'ROLE_USER','用户角色'); insert into user_role(user_id,role_id) values(1,1); insert into user_role(user_id,role_id) values(1,2); insert into user_role(user_id,role_id) values(2,2);
现在我们要在这样的数据结构基础上使用Spring Security,Spring Security所需要的数据只是为了处理两种情况,一是判断登录用户是否合法,二是判断登陆的用户是否有权限访问受保护的系统资源。
我们所要做的工作就是在现有数据结构的基础上,为Spring Security提供这两种数据。
当用户登陆时,系统需要判断用户登录名是否存在,登陆密码是否正确,当前用户是否被禁用。我们使用下列SQL来提取这三个信息。
select username,password,status as enabled from user where username=?
用户登陆之后,系统需要获得该用户的所有权限,根据用户已被赋予的权限来判断哪些系统资源可以被用户访问,哪些资源不允许用户访问。
以下SQL就可以获得当前用户所拥有的权限。
select u.username,r.name as authority from user u join user_role ur on u.id=ur.user_id join role r on r.id=ur.role_id where u.username=?"/>
将这两条SQL语句配置到xml中,就可以让Spring Security从我们自定义的表结构中提取数据了。最终配置文件如下所示:
<authentication-provider> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password,status as enabled from user where username=?" authorities-by-username-query="select u.username,r.name as authority from user u join user_role ur on u.id=ur.user_id join role r on r.id=ur.role_id where u.username=?"/> </authentication-provider>
实例见ch003。