- 支持HTTP basic的authentication
- 支持HTTP Digest的authentication
- 支持Form based的authentication
- 可以与一些开源SSO项目如CAS集成
- 支持remember me的功能
- 可以与JBoss、Tomcat等container的j2ee标准认证方式集成。
- 支持acl
为了方便讲解,我挑了一个例子,一个公司的人员管理系统,一个公司分成几个部门,每个部门下面有主管和员工,我将逐步增加对安全的要求,首先的一个基本要求是公司的网站有一部分是所有用户都能访问的,而一部分URL只有登录用户才能访问,首先我们来实现这个功能。
我们使用appfuse来进行讲解,appfuse是一个非常容易上手的开源项目,它已经集成了spring、hibernate、struts等等,当然,它也配置了acegi。从www.appfuse.org上下载最新的版本1.9.3. 然后解开。我下载的是spring MVC + hibernate版本。
在appfuse里面,安全相关的配置都存放在web/security.xml里面,打开该文件,可以看到filterChainProxy里面的配置/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,这么多的filter,是不是晕了头了?呵呵,别急,我将一一讲述各个filter的作用。
发布appfuse后可以看到,所有的*.html都被保护了起来,但现在我们的需求是任何用户都可以看到一个首页,不需要登录。我们来写一个spring controller。
public class MainController extends AbstractController {
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("mainPage");
}
}
这个controller的作用仅仅是转到mainPage.jsp这个页面,这个页面存放在web/page中。我们在这里加入一个mainPage.jsp。
<%@ page language="java" contentType="text/html; charset=gbk"
pageEncoding="GBK"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ include file="/common/taglibs.jsp"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>Insert title here</title>
</head>
<body>
这里是主页
</body>
然后我们在web/action-servlet里面加入该controller的定义和对应的URL
<bean id="mainController" class="org.appfuse.webapp.action.MainController">
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="messageInterceptor"/>
</list>
</property>
<property name="mappings">
<props>
<prop key="/editProfile.html">userFormController</prop>
<prop key="/mainMenu.html">filenameController</prop>
<prop key="/editUser.html">userFormController</prop>
<prop key="/selectFile.html">fileUploadController</prop>
<prop key="/uploadFile.html">fileUploadController</prop>
<prop key="/passwordHint.html">passwordHintController</prop>
<prop key="/signup.html">signupController</prop>
<!-- Add additional URL mappings here -->
<prop key="/main.html">mainController</prop>
</props>
</property>
</bean>
我们把web/index.jsp里面的redirect指向到我们的controller
<%@ include file="/common/taglibs.jsp"%>
<c:redirect url="/main.html"/>
如果我们这时访问主页面,会要求我们输入用户名密码进行验证,这时我们在web/security.xml的filterInvocationInterceptor里面加入一行
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/main.html*=ROLE_ANONYMOUS,admin,user
/clickstreams.jsp*=admin
/flushCache.*=admin
/passwordHint.html*=ROLE_ANONYMOUS,admin,user
/reload.*=admin
/signup.html*=ROLE_ANONYMOUS,admin,user,xakee
/users.html*=admin
/**/*.html*=admin,user
</value>
</property>
</bean>
注意上面/main.html*的定义,这里的定义表示具有ROLE_ANONYMOUS,admin,user三种角色的用户都可以访问该URL,ROLE_ANONYMOUS就表示匿名用户。这样任何用户就都可以访问/main.html这个页面了。下次我将逐一讲解各个filter的作用以及ROLE_ANONYMOUS这个角色是如果赋给匿名用户的。