第 1 章 一个简单的HelloWorld

Spring Security中可以使用Acegi-1.x时代的普通配置方式,也可以使用从2.0时代才出现的命名空间配置方式,实际上这两者实现的功能是完全一致的,只是新的命名空间配置方式可以把原来需要几百行的配置压缩成短短的几十行。我们的教程中都会使用命名空间的方式进行配置,凡事务求最简。

1.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的检测,这从第一时间把没有授权的请求排除在系统之外,保证系统资源的安全。关于过滤器配置的更多讲解可以参考http://www.mossle.com/docs/jsp/html/jsp-ch-07.html#jsp-ch-07-03-01

1.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.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

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

	<authentication-manager>
        <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>
    </authentication-manager>

</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。

access指定的权限部分比较有趣,大家可以注意到这些权限标示符都是以ROLE_开头的,实际上这与Spring Security中的Voter机制有着千丝万缕的联系,只有包含了特定前缀的字符串才会被Spring Security处理。目前来说我们只需要记住这一点就可以了,在教程以后的部分中我们会详细讲解Voter的内容。

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允许访问的资源。

1.3. 完善整个项目

因为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权限的用户才能访问。

最终我们的整个项目会变成下面这样:

+ ch001/
  + src/
    + main/
      + resources/
        * applicationContext.xml
      + webapp/
        + WEB-INF/
          * web.xml
        * admin.jsp
        * index.jsp
    + test/
      + resources/
  * pom.xml
        

1.4. 运行示例

首先确保自己安装了Maven2。如果之前没用过Maven2,可以参考我们的Maven2教程http://www.mossle.com/docs/maven/html/index.html

安装好Maven2之后,进入ch001目录,然后执行mvn。

信息: Root WebApplicationContext: initialization completed in 1578 ms
2009-05-28 11:37:50.171::INFO:  Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 10 seconds.
        

等到项目启动完成后。打开浏览器访问http://localhost:8080/ch001/就可以看到登陆页面。

用户登陆

图 1.1. 用户登陆


这个简陋的页面是Spring Security自动生成的,一来为了演示的方便,二来避免用户自己编写登陆页面时犯错,Spring Security为了避免可能出现的风险,连测试用的登录页面都自动生成出来了。在这里我们就省去编写登陆页面的步骤,直接使用默认生成的登录页面进行演示吧。

首先让我们输入一个错误用的用户名或密码,这里我们使用test/test,当然这个用户是不存在的,点击提交之后我们会得到这样一个登陆错误提示页面。

登陆失败

图 1.2. 登陆失败


如果输入的是正确的用户名和密码,比如user/user,系统在登陆成功后会默认跳转到index.jsp。

登陆成功

图 1.3. 登陆成功


这时我们可以点击admin.jsp链接访问admin.jsp,也可以点击logout进行注销。

如果点击了logout,系统会注销当前登陆的用户,然后跳转至登陆页面。如果点击了admin.jsp链接就会显示如下页面。

拒绝访问

图 1.4. 拒绝访问


很遗憾,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.jsp

图 1.5. 显示admin.jsp


根据我们之前的配置,admin用户拥有ROLE_ADMIN和ROLE_USER两个权限,因为他拥有ROLE_USER权限,所以可以访问/index.jsp,因为他拥有ROLE_ADMIN权限,所以他可以访问/admin.jsp。

至此,我们很高兴的宣布,咱们已经正式完成,并运行演示了一个最简单的由Spring Security保护的web系统,下一步我们会深入讨论Spring Security为我们提供的其他保护功能,多姿多彩的特性。