第 2 章 使用数据库管理用户权限

上一章节中,我们把用户信息和权限信息放到了xml文件中,这是为了演示如何使用最小的配置就可以使用Spring Security,而实际开发中,用户信息和权限信息通常是被保存在数据库中的,为此Spring Security提供了通过数据库获得用户权限信息的方式。

2.1. 修改配置文件

为了从数据库中获取用户权限信息,我们所需要的仅仅是修改配置文件中的authentication-provider部分。

将上一章配置文件中的user-service替换为jdbc-user-service,替换内容如下所示:

<authentication-provider>
    <user-service>
        <user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />
        <user name="user" password="user" authorities="ROLE_USER" />
    </user-service>
</authentication-provider>
        

将上述红色部分替换为下面黄色部分。

<authentication-provider>
    <jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
        

现在只要再为jdbc-user-service提供一个dataSource就可以让Spring Security使用数据库中的权限信息了。在此我们使用spring创建一个演示用的dataSource实现,这个dataSource会连接到hsqldb数据库,从中获取用户权限信息。[1]

<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <beans:property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
    <beans:property name="url" value="jdbc:hsqldb:res:/hsqldb/test"/>
    <beans:property name="username" value="sa"/>
    <beans:property name="password" value=""/>
</beans:bean>
        

最终的配置文件如下所示:

<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <http auto-config='true'>
        <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />
        <intercept-url pattern="/**" access="ROLE_USER" />
    </http>

    <authentication-manager>
        <authentication-provider>
            <jdbc-user-service data-source-ref="dataSource"/>
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <beans:property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <beans:property name="url" value="jdbc:hsqldb:res:/hsqldb/test"/>
        <beans:property name="username" value="sa"/>
        <beans:property name="password" value=""/>
    </beans:bean>
</beans:beans>
        

2.2. 数据库表结构

Spring Security默认情况下需要两张表,用户表和权限表。以下是hsqldb中的建表语句:

create table users(1
    username varchar_ignorecase(50) not null primary key,
    password varchar_ignorecase(50) not null,
    enabled boolean not null
);

create table authorities (2
    username varchar_ignorecase(50) not null,
    authority varchar_ignorecase(50) not null,
    constraint fk_authorities_users foreign key(username) references users(username)
);

create unique index ix_auth_username on authorities (username,authority);3
        

1

users:用户表。包含username用户登录名,password登陆密码,enabled用户是否被禁用三个字段。

其中username用户登录名为主键。

2

authorities:权限表。包含username用户登录名,authorities对应权限两个字段。

其中username字段与users用户表的主键使用外键关联。

3

对authorities权限表的username和authority创建唯一索引,提高查询效率。

Spring Security会在初始化时,从这两张表中获得用户信息和对应权限,将这些信息保存到缓存中。其中users表中的登录名和密码用来控制用户的登录,而权限表中的信息用来控制用户登陆后是否有权限访问受保护的系统资源。

我们在示例中预先初始化了一部分数据:

insert into users(username,password,enabled) values('admin','admin',true);
insert into users(username,password,enabled) values('user','user',true);

insert into authorities(username,authority) values('admin','ROLE_ADMIN');
insert into authorities(username,authority) values('admin','ROLE_USER');
insert into authorities(username,authority) values('user','ROLE_USER');
        

上述sql中,我们创建了两个用户admin和user,其中admin拥有ROLE_ADMIN和ROLE_USER权限,而user只拥有ROLE_USER权限。这和我们上一章中的配置相同,因此本章实例的效果也和上一章完全相同,这里就不再赘述了。

实例见ch002。



[1] javax.sql.DataSource是一个用来定义数据库连接池的统一接口。当我们想调用任何实现了javax.sql.DataSource接口的连接池,只需要调用接口提供的getConnection()就可以获得连接池中的jdbc连接。javax.sql.DataSource可以屏蔽连接池的不同实现,我们使用的连接池即可能由第三方包单独提供,也可能是由j2ee容器统一管理提供的。