这篇文章我只讲spring security的配置使用,而不会去讨论它的适用场景,spring security主要是面向web开发的一个安全框架,与之相对应的还有Apache的Shrio
,
适用范围也更广些。要想从全局上了解某个框架产品的功能特性,适用场景等,最好看它们的overview。
这篇文章会介绍Spirng Security3.1的一些新特性,先列出来
•
Support for multiple http elements
(支持多个http元素
)
• Added Basic Crypto Module(添加了加密算法的支持,该模块可以单独使用)
• Support clearing cookies on logout(支持登出后清除cookie)
当然了还有很多新特性,具体请参照官方文档。下面就开始我们的step-by-setp.
首先是要把Spring Security的类库加入到我们应用的类路径中,对于使用maven的用户来说,很简单,添加如下依赖即可:
<properties>
<springSecurity.version>3.1.0.RELEASE</springSecurity.version>
</properties>
<!-- Spring Security 3 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${springSecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springSecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springSecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${springSecurity.version}</version>
</dependency>
第2步,在web.xml中添加一个过滤器:
<!-- Enables Spring Security -->
<!--
If you're using some other framework that is also filter-based, then you need to make sure that the Spring
Security filters come first. Examples are the use of SiteMesh to decorate your web pages
-->
<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>
这里有两点需要注意下,首先该过滤器类是spring framwork包中提供的,并不属于spring security,
但是filter-name是有特殊含义的,该过滤器类的主要作用就是将web请求拦截下来然后DelegatingFilterProxy会从spring这个大容器中寻找名为springSecurityFilterChain的这个bean来处理安全方面的事情,其实
DelegatingFilterProxy就是在web请求和spring security之间的一座桥梁。第二点要注意的是如果你还是用了其他基于过滤器的框架,比如sitemesh,这时我们一定要确保把springSecurityFilterChain这个过滤器的filter-mapping放在第一位,这是spring security官网文档里提到的,实际中我也遇到过此问题,也是使用了sitemesh结果没放在第一位导致一些问题。
第3步,配置spring security:
<?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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- Spring Security3.1 support multi-http config -->
<http pattern="/resources/*" security="none" />
<http pattern="/login" security="none" />
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/hello.jsp" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin.jsp" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/*" access="hasRole('ROLE_USER')" />
<form-login login-page="/login"
login-processing-url="/loginProcess"
authentication-failure-url="/login?error=1"
default-target-url="/" />
<remember-me key="SpringSecurityAclDemo-rmkey-BUUttZnBJCa#U=4Dwg@%5_ptCC8wHtlY"
data-source-ref="dataSource" />
<logout logout-url="/logout" logout-success-url="/" invalidate-session="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="jdbcUserService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<beans:bean id="jdbcUserService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"
p:dataSource-ref="dataSource"
p:enableGroups="true"
p:enableAuthorities="false" />
</beans:beans>
这里我们使用security作为默认的命名空间,下面简单介绍下里面各种配置元素的作用吧,最好先阅读下官方文档的Part II. Architecture and Implementation
这一章节的内容,从总体上了解spring security的整体架构和一些细节内容。要想详细了解请参考官方文档或者Spring Security 3这本书,这两个pdf文件我都会在附件中给出。其中http的use-expression属性为true表示我们使用spring 3的EL表达式,使用EL表达式可以完成一些比较复杂且有意思的操作。form-login子元素应该很好理解,login-page就表示请求登录页面的url,login-process-url 表示处理登录验证的url,authentication-failure-url,表示认证失败的url,default-target-url表示登录成功后默认重定向到的url,如果我们没登陆就去请求一个受保护的url,那么系统就会缓存我们这次请求的url,然后让我们先登录,登录完成后并且该用户拥有访问该资源的权限,那么系统就会再次将我们重定向到之前访问的url。
remember-me元素key属性是必须的,为了确保系统的安全性,我们最好将key弄得足够复杂,可以是应用名称加上随机生成的一个字符串(可以找online password generator帮忙)
,
如果我们加上了data-source-ref属性,就表示我们会把remember-me的一些信息保存到数据库中,这就需要我们添加一个如下的表结构定义到数据库中:
create table persistent_logins(
username varchar(50) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);
这样做有几个优点,第一比较安全,第二服务器重启后仍可使用remember-me自动登录。
下面粗略讲讲authentication-manager元素,authentication-provider 的 password-encoder-ref表示用来对密码进行加密处理的一个bean,该bean是crypto模块中的org.springframework.security.crypto.password.StandardPasswordEncoder
,该bean采用的是SHA-256加密算法并随即产生8位byte值作为salt值,加密后密码长度为80位,加密强度非常高,推荐直接使用。该bean实现了org.springframework.security.crypto.password.PasswordEncoder
接口,该接口提供了两个方法:
package org.springframework.security.crypto.password;
/**
* Service interface for encoding passwords.
* @author Keith Donald
*/
public interface PasswordEncoder {
/**
* Encode the raw password.
* Generally, a good encoding algorithm applies a SHA-1 or greater hash combined with an 8-byte or greater randomly
* generated salt.
*/
String encode(CharSequence rawPassword);
/**
* Verify the encoded password obtained from storage matches the submitted raw password after it too is encoded.
* Returns true if the passwords match, false if they do not.
* The stored password itself is never decoded.
*
* @param rawPassword the raw password to encode and match
* @param encodedPassword the encoded password from storage to compare with
* @return true if the raw password, after encoding, matches the encoded password from storage
*/
boolean matches(CharSequence rawPassword, String encodedPassword);
}
方法很直观,第一个用来获取加密后的密码,第二个用来验证密码是否正确。
对jdbcUserService这个bean得好好说道说道,因为我们采用的是"用户-组-权限"这种方案,对于用户非常少的也可以直接采用"用户-权限"
,
像windows操作系统和linux操作系统的用户管理采用的都是前者
。
对于一些历史遗留的表结构,需要做些小的调整,将适配你表结构的sql查询语句通过属性注入到jdbcUserService中去,具体查看下org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl
这个类的文档就可以了,可以仿照原来的sql语句来写,也不复杂。
差点忘了,那个
"用户-组-权限"方案的表定义语句,还没贴出来呢,其实这些都在官方文档的附录中有。
create table users(
username varchar(50) not null primary key,
password varchar(80) not null,
enabled boolean not null default true
);
create table groups(
id int(11) primary key auto_increment,
group_name varchar(50) not null
);
create table group_authorities(
group_id int(11) not null,
authority varchar(50) not null,
constraint fk_group_authorities_groups foreign key(group_id) references groups(id)
);
create table group_members(
id int(11) primary key auto_increment,
username varchar(50) not null,
group_id int(11) not null,
constraint fk_group_members_groups foreign key(group_id) references groups(id)
);
第4步,编写登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<form action="<c:url value="/loginProcess" />" method="post">
<c:if test="${not empty param.error}">
<div id="message" class="error">用户名或密码错误</div>
</c:if>
<fieldset>
<p>
<label for="j_username" class="label">用户名</label>
<input type="text" name="j_username" id="j_username"/>
</p>
<p>
<label for="j_password" class="label">密码</label>
<input type="password" name="j_password" id="j_password"/>
</p>
<p>
<label class="label">两周内自动登录</label>
<input id="remember_me" name="_spring_security_remember_me" type="checkbox"/>
</p>
<p><input id="loginBtn" class="btn" type="submit" value="登录"/></p>
</fieldset>
</form>
</body>
</html>
form action就是我们在我们在配置文件中的login-processing-url
的url,用户名和密码的name分别为j_username
和j_password
,当然这两个名称也是可以自定义的,那个checkbox的name为_spring_security_remember_me
是remember-me
用来实现自动登录的。
测试sql语句如下:clong的密码是110,admin的密码是admin
insert into users(username, password, enabled) values ('clong', '532bf9d4d3213a14d232f3a548a0cf1aa47fbf105ee7896175587c109e9663522df0cdf9efd5fd97', true);
insert into users(username, password, enabled) values ('admin', '83ed8f60f97d7f1cc03fc583553ad1f71d6db79d2a8b613dc9493f1923c92b27204529dcf21b0877', true);
insert into groups(group_name) values ('User');
insert into groups(group_name) values ('Administrator');
insert into group_authorities(group_id, authority) select id, 'ROLE_USER' from groups where group_name='User';
insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Administrator';
insert into group_authorities(group_id, authority) select id, 'ROLE_ADMIN' from groups where group_name='Administrator';
insert into group_members(username, group_id) select 'clong', id from groups where group_name='User';
insert into group_members(username, group_id) select 'admin', id from groups where group_name='Administrator';
接下来来做个测试,我们在intercept-url定义了一些访问限制规则,对于请求/的url一律放行,对于请求/hello.jsp的url需要登录后并且所在组为"User"的可以访问,对于请求/admin.jsp需要登录,但是”User“组的和匿名用户都访问不了,只有”Administrator“组的用户才可以访问
。
接下来有时间的话,会分享一下自己学习Spring Security中ACL(Access Control List)的东西,这个acl模块比较强大,复杂的应用肯定不仅仅是控制一些url和方法级别的保护,而是需要让系统知道这个对象是否有权限访问该业务方法,动态地去判断,当然它也有缺点,特别当领域对象的实例超过百万级别的时候,
对数据库的压力比较大,不过对中小规模的系统完全没有问题。附件中提供的源码也包含了一个简单的acl demo,没有将两者分开,自己写在一起了,凑合着看吧,记得改下数据库密码执行下sql就可以运行了。 运行:mvn clean jetty:run,或者打包放到tomcat里直接跑
- 大小: 21.5 KB
分享到:
相关推荐
Spring Security 3.x 完整入门教程 源代码 MyEclipse工程,请大家自己加入lib。
主题: Spring Security —— 演讲者 张明星 1、Traditional Web App Security Dev 2、Spring Security 2.x Quick Start 3、Spring Security 2.x Overview 4、Dive Into Spring Security Authentication ...
Spring Data JPA系列4——Spring声明式事务处理与多数据源支持.doc
spring security3 中文版本
Spring Security 3.pdf Spring Security 3.pdf Spring Security 3.pdf Spring Security 3.pdf
Spring Security三份资料,实战Spring Security 3.x.pdf;Spring Security 3.pdf;Spring Security使用手册.pdf
即使用一个基于Spring3的web工程作为基础,以理解使用Spring Security3使其保证安全的概念和策略。 不管你是不是已经使用Spring Security还是只是对这个软件有兴趣,就都会在本书中得到有用的信息。 在本节的内容中,你...
struts2 + spring3 + hibernate3 + spring security3 + mysql + tomcat sys_users;sys_roles;sys_authorities;sys_resources;sys_users_roles;sys_roles_authorities;sys_authorities_resources; PS:此项目运行不...
springsecurity是一个功能强大且高度可定制的身份验证和访问控制框架。springsecurity是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring安全性的真正威力在于它可以很容易地扩展以...
SpringSecurity学习总结源代码
spring security spring security 中文文档
简单的 springSecurity3例子代码
项目应用到spring3,security3,hibernate4,struts2;应用中涉及到安全认证,目前项目有独立的统一认证网关,所以登录时只需要将安全认证网关的认证后信息塞到spring security中,由security3来管理用户的权限设置。...
Spring Security:spring家族一员。是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转...
(1)该项目是基于spring3+struts2+hibernate3+spring security3的权限管理项目 (2)后台我已经实现了权限管理,包括用户,角色和资源的分配。前台实现了spring security3的管理 (3)网上案例普遍是后台单一登陆。...
spring-security3入门教程。
该资源是基本Spring Security实战七篇文档中组织的源码,详情如下: ssecurity项目是Spring Security实战(一和二)的源码; ssecurity-db项目是Spring Security实战(三)的源码; ssceurity-page项目是Spring ...
SpringSecurity入门教程,完整可运行的实例
Spring Security in Action