Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
——以上摘自百度百科
在一开始,我们主要谈谈怎么配置 Spring Security,怎么使用Spring Security。这里使用的spring-security是spring-security-core-2.0.5的版本,应该是比较老的版本,但是作为了解一下spring-security还是可以的。
一、一个简单的HelloWorld
Spring Security 中可以使用Acegi-1.x 时代的普通配置方式,也可以使用从2.0 时代才出现的命名空间配置方式,实际上这两者实现的功能是完全一致的,只是新的命名空间配置方式可以把原来需要几百行的配置压缩成短短的几十行。我们的教程中都会使用命名空间的方式进行配置,凡事务求最简。
1.配置过滤器
为了在项目中使用 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>
所有的用户在访问项目之前,都要先通过Spring Security的检测,这从第一时间把没有授权的请求排除在系统之外,保证系统资源的安全。
2.在 applicationContext.xml 中使用Spring Security 提供的命名空间进行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" ------------1
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-2.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
<http auto-config='true'> ---------------2
<intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" /> ---------------3
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" /> ---------------4
<user name="user" password="user" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</beans:beans>
其中 :
1:声明在xml 中使用Spring Security 提供的命名空间
2:http 部分配置如何拦截用户请求。auto-config='true'将自动配置几种常用的权限控制机制,包括form, anonymous, rememberMe。
3:我们利用intercept-url 来判断用户需要具有何种权限才能访问对应的url资源,可以在pattern 中指定一个特定的url 资源,也可以使用通配符指定一组类似的url 资源。例子中定义的两个intercepter-url,第一个用来控制对/admin.jsp 的访问,第二个使用了通配符/**,说明它将控制对系统中所有url 资源的访问。在实际使用中,Spring Security 采用的是一种就近原则,就是说当用户访问的url 资源满足多个intercepter-url 时,系统将使用第一个符合条件的intercept-url 进行权限控制。在我们这个例子中就是,当用户访问/admin.jsp 时,虽然两个intercept-url 都满足要求,但因为第一个intercept-url 排在上面,所以Spring Security 会使用第一个intercept-url 中的配置处理对/admin.jsp 的请求,也就是说,只有那些拥有了ROLE_ADMIN 权限的用户才能访问/admin.jsp。
4:user-service 中定义了两个用户,admin 和user。为了简便起见,我们使用明文定义了两个用户对应的密码,这只是为 了当前演示的方便,之后的例子中我们会使用Spring Security 提供的加密方式,避免用户密码被他人窃取。最最重要的 部分是authorities,这里定义了这个用户登陆之后将会拥有的权限,它与上面intercept-url 中定义的权限内容一一对应。每个用户可以同时拥有多个权限,例子中的admin 用户就拥有ROLE_ADMIN 和ROLE_USER两种权限,这使得admin 用户在登陆之后可以访问ROLE_ADMIN 和ROLE_USER允许访问的所有资源。与之对应的是,user 用户就只拥有ROLE_USER 权限,所以他只能访问ROLE_USER 允许访问的资源,而不能访问ROLE_ADMIN 允许访问的资源。
因为 Spring Security 是建立在Spring 的基础之上的,所以web.xml 中除了需要配置我们刚刚提到的过滤器,还要加上加载Spring 的相关配置。最终得到的web.xml看起来像是这样:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
演示不同权限的用户登陆之后可以访问不同的资源,我们为项目添加了两个jsp文件,admin.jsp 和index.jsp。其中admin.jsp 只有那些拥有ROLE_ADMIN 权限的用户才能访问,而index.jsp 只允许那些拥有ROLE_USER 权限的用户才能访问。
最终我们的整个项目会变成下面这样:
等到项目启动完成后。打开浏览器访问http://localhost:8080/ch001/就可以看到登陆页面。
这个简陋的页面是 Spring Security 自动生成的,一来为了演示的方便,二来避免用户自己编写登陆页面时犯错,Spring Security 为了避免可能出现的风险,连测试用的登录页面都自动生成出来了。在这里我们就省去编写登陆页面的步骤,直接使用默认生成的登录页面进行演示吧。首先让我们输入一个错误用的用户名或密码,这里我们使用 test/test,当然这个用户是不存在的,点击提交之后我们会得到这样一个登陆错误提示页面。
如果输入的是正确的用户名和密码,比如user/user,系统在登陆成功后会默认跳转到index.jsp。
这时我们可以点击 admin.jsp 链接访问admin.jsp,也可以点击logout 进行注销。很遗憾,user 用户是无法访问/admin.jsp 这个url 资源的,这在上面的配置文件中已经有过深入的讨论。我们在这里再简要重复一遍:user 用户拥有ROLE_USER权限,但是/admin.jsp 资源需要用户拥有ROLE_ADMIN 权限才能访问,所以当user 用户视图访问被保护的/admin.jsp 时,Spring Security 会在中途拦截这一请求,返回拒绝访问页面。为了正常访问 admin.jsp,我们需要先点击logout 注销当前用户,然后使用admin/admin 登陆系统,然后再次点击admin.jsp 链接就会显示出admin.jsp 中的内容。
根据我们之前的配置,admin 用户拥有ROLE_ADMIN 和ROLE_USER 两个权限,因为他拥有ROLE_USER 权限,所以可以访问/index.jsp,因为他拥有ROLE_ADMIN 权限,所以他可以访问/admin.jsp。