spring中没有提供默认的权限管理模块,而是基于Acegi开发了一个spring-security,它是基于spring的用户权限认证框架。spring-security是一个比较轻量的权限认证框架,它没有实现管理界面,只给出了相应的接口。
配置spring-security
在web.xml配置文件中添加过滤器:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
然后在<classpath>路径下创建配置文件PROJECT-security.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
同时将该配置文件加到web.xml的 <context-param> 里。
spring-security中使用角色来分类管理用户权限,如上面的配置中就包含了ROLE_ADMIN和ROLE_USER两个角色,并分别有/admin/和/user/的URL路径下的权限。
在数据库中保存用户帐号
用户的帐号密码有几种不同的方式保存,包括xml中、LDAP和数据库中等。上面使用的是保存到数据库中的方式,使用了之前在applicationContext.xml中配置的dataSource bean。使用数据库保存帐号时,需要按照spring-security规定的字段来建表,有两个相关的表,分别用于保存帐号密码和登录状态。使用MySQL可以这样创建:
1 CREATE TABLE `user` ( 2 `account` varchar(50) NOT NULL, 3 `password` varchar(50) NOT NULL, 4 `authority` varchar(50) NOT NULL, 5 `status` tinyint(1) NOT NULL, 6 UNIQUE KEY `account` (`account`), 7 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 8 9 CREATE TABLE `persistent_logins` ( 10 `username` varchar(64) NOT NULL, 11 `series` varchar(64) NOT NULL, 12 `token` varchar(64) NOT NULL, 13 `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 14 PRIMARY KEY (`series`) 15 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
加密用户密码
默认spring-security中采用明文方式存储密码,可以通过设置 <password-encoder> 来对密码加密。这时对应的用户注册模块也要将密码以加密后的数据保存到数据库中才行。
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
import org.springframework.security.providers.encoding.PasswordEncoder;
PasswordEncoder encoder = new Md5PasswordEncoder();
String password = encoder.encodePassword(form.getPassword(), null);
阻止用户重复登录
可以通过会话控制来防止用户重复登录,这可以通过配置来实现。首先在web.xml中添加监听:
<listener>
<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
然后在PROJECT-security.xml配置文件中的 <http></http> 内添加:
<concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true" />
max-sessions="1" 表示该用户同时登录的最大会话数为1, exception-if-maximum-exceeded="true" 表示阻止超出的用户登录。
在jsp中加入spring-security
spring-security给出了在jsp中使用的接口。用户登录可以使用下面的表单:
<form name='f' action='/PROJECT/j_spring_security_check' method='POST'>
<table>
<tr><td>用户名:</td><td><input type='text' name='j_username' value=''></td></tr>
<tr><td>密码:</td><td><input type='password' name='j_password'/></td></tr>
<tr><td></td><td><input type='checkbox' name='_spring_security_remember_me'/> 自动登录</td></tr>
<tr><td colspan='2' align="right"><input name="reset" id="reset" type="reset" value="重置" />
<input name="submit" id="submit" type="submit" value="登录" /></td></tr>
</table>
</form>
根据登录用户进行条件判断可以使用下面的方式:
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<sec:authorize ifAllGranted="ROLE_ANONYMOUS">
</sec:authorize>
<sec:authorize ifAllGranted="ROLE_USER">
</sec:authorize>
在特定jsp页面获取登录用户的帐号的方法是:
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<input name="customer" type="hidden" value="<sec:authentication property='principal.username' />" />
spring-security还有很多相关的用法,可以查看 官方的文档 。