acegi安全系统,是一个用于spring framework的安全框架,能够和目前流行的web容器无缝集成。它使用了spring的方式提供了安全和认证安全服务,包括使用bean context,拦截器和面向接口的编程方式。因此,acegi安全系统能够轻松地适用于复杂的安全需求。
安全涉及到两个不同的概念,认证和授权。前者是关于确认用户是否确实是他们所宣称的身份。授权则是关于确认用户是否有允许执行一个特定的操作。
在acegi安全系统中,需要被认证的用户,系统或代理称为"principal"。acegi安全系统和其他的安全系统不同,它并没有角色和用户组的概念。
acegi系统设计
关键组件
acegi安全系统包含以下七个关键的功能组件:
1 authentication对象,包含了principal,credential和principal的授权信息。同时还可以包含关于发起认证请求的客户的其他信息,如ip地址。
2 contextholder对象,使用threadlocal储存authentication对象的地方。
3 authenticationmanager,用于认证contextholder中的authentication对象。
4 accessdecissionmanager,用于授权一个特定的操作。
5 runasmanager,当执行特定的操作时,用于选择性地替换authentication对象。
6 secure object拦截器,用于协调authenticationmanager,accessdecissionmanager,runasmanager和特定操作的执行。
7 objectdefinitionsource,包含了特定操作的授权定义。
这七个关键的功能组件的关系如下图所示(图中灰色部分是关键组件):
安全管理对象
acegi安全系统目前支持两类安全管理对象。
第一类的安全管理对象管理aop alliance的methodinvocation,开发人员可以用它来保护spring容器中的业务对象。为了使spring管理的bean可以作为methodinvocation来使用,bean可以通过proxyfactorybean和beannameautoproxycreator来管理,就像在spring的事务管理一样使用。
第二类是filterinvocation。它用过滤器(filter)来创建,并简单地包装了http的servletrequest,servletresponse和filterchain。filterinvocation可以用来保护http资源。通常,开发人员并不需要了解它的工作机制,因为他们只需要将filter加入web.xml,acegi安全系统就可以工作了。
安全配置参数
每个安全管理对象都可以描述数量不限的各种安全认证请求。例如,methodinvocation对象可以描述带有任意参数的任意方法的调用,而filterinvocation可以描述任意的http url。
acegi安全系统需要记录应用于每个认证请求的安全配置参数。例如,对于bankmanager.getbalance(int accountnumber)方法和bankmanager.approveloan(int applicationnumber)方法,它们需要的认证请求的安全配置很不相同。
为了保存不同的认证请求的安全配置,需要使用配置参数。从实现的视角来看,配置参数使用configattribute接口来表示。acegi安全系统提供了configattribute接口的一个实现,securityconfig,它把配置参数保存为一个字符串。
configattributedefinition类是configattribute对象的一个简单的容器,它保存了和特定请求相关的configattribute的集合。
当安全拦截器收到一个安全认证请求时,需要决定应用哪一个配置参数。换句话说,它需要找出应用于这个请求的configattributedefinition对象。这个查找的过程是由objectdefinitionsource接口来处理的。这个接口的主要方法是public configattributedefinition getattributes(object object),其中object参数是一个安全管理对象。因为安全管理对象包含有认证请求的详细信息,所以objectdefinitionsource接口的实现类可以从中获得所需的详细信息,以查找相关的configattributedefiniton对象。
acegi如何工作
为了说明acegi安全系统如何工作,我们设想一个使用acegi的例子。通常,一个安全系统需要发挥作用,它必须完成以下的工作:
1 首先,系统从客户端请求中获得principal和credential;
2 然后系统认证principal和credential信息;
3 如果认证通过,系统取出principal的授权信息;
4 接下来,客户端发起操作请求;
5 系统根据预先配置的参数检查principal对于该操作的授权;
6 如果授权检查通过则执行操作,否则拒绝。
那么,acegi安全系统是如何完成这些工作的呢?首先,我们来看看acegi安全系统的认证和授权的相关类:
安全拦截器的抽象基类,它包含有两个管理类,authenticationmanager和accessdecisionmanager。authenticationmanager用于认证contextholder中的authentication对象(包含了principal,credential和principal的授权信息);accessdecissionmanager则用于授权一个特定的操作。
下面来看一个methodsecurityinterceptor的例子:
<bean id="bankmanagersecurity"
class=".net.sf.acegisecurity.intercept.method.methodsecurityinterceptor">
<property name="validateconfigattributes">
<value>true</value>
</property>
<property name="authenticationmanager">
<ref bean="authenticationmanager"/>
</property>
<property name="accessdecisionmanager">
<ref bean="accessdecisionmanager"/>
</property>
<property name="objectdefinitionsource">
<value>
.net.sf.acegisecurity.context.bankmanager.delete*=
role_supervisor,run_as_server
.net.sf.acegisecurity.context.bankmanager.getbalance=
role_teller,role_supervisor,banksecurity_customer,run_
</value>
</property>
</bean>
<bean id="authenticationdao" class=".net.sf.acegisecurity.providers.dao.jdbc.jdbcdaoimpl">
<property name="datasource"><ref bean="datasource"/></property>
</bean>
<bean id="daoauthenticationprovider"
class=".net.sf.acegisecurity.providers.dao.daoauthenticationprovider">
<property name="authenticationdao"><ref bean="authenticationdao"/></property>
</bean>
<bean id="authenticationmanager" class=".net.sf.acegisecurity.providers.providermanager">
<property name="providers">
<list><ref bean="daoauthenticationprovider"/></list>
</property>
</bean>
<bean id="rolevoter" class=".net.sf.acegisecurity.vote.rolevoter"/>
<bean id="accessdecisionmanager" class=".net.sf.acegisecurity.vote.affirmativebased">
<property name="allowifallabstaindecisions"><value>false</value></property>
<property name="decisionvoters">
<list><ref bean="rolevoter"/></list>
</property>
</bean>
log4j.rootlogger=debug, stdout, r
log4j.appender.stdout=org.apache.log4j.consoleappender
log4j.appender.stdout.layout=org.apache.log4j.patternlayout
# pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.conversionpattern=%5p [%t] (%f:%l) - %m%n
log4j.appender.r=org.apache.log4j.rollingfileappender
log4j.appender.r.file=example.log
log4j.appender.r.maxfilesize=100kb
# keep one backup file
log4j.appender.r.maxbackupindex=1
log4j.appender.r.layout=org.apache.log4j.patternlayout
log4j.appender.r.layout.conversionpattern=%p %t %c - %m%n
import com.foo.bar;
import org.apache.log4j.logger;
import org.apache.log4j.propertyconfigurator;
public class myapp {
static logger logger = logger.getlogger(myapp.class.getname());
public static void main(string[] args) {
// basicconfigurator replaced with propertyconfigurator.
propertyconfigurator.configure(args[0]);
logger.info("entering application.");
bar bar = new bar();
bar.doit();
logger.info("exiting application.");
}
}
<filter>
<filter-name>acegi channel processing filter</filter-name>
<filter-class>.net.sf.acegisecurity.util.filtertobeanproxy</filter-class>
<init-param>
<param-name>targetclass</param-name>
<param-value>.net.sf.acegisecurity.securechannel.channelprocessingfilter</param-value>
</init-param>
</filter>
<filter>
<filter-name>acegi authentication processing filter</filter-name>
<filter-class>.net.sf.acegisecurity.util.filtertobeanproxy</filter-class>
<init-param>
<param-name>targetclass</param-name>
<param-value>.net.sf.acegisecurity.ui.webapp.authenticationprocessingfilter</param-value>
</init-param>
</filter>
<filter>
<filter-name>acegi http basic authorization filter</filter-name>
<filter-class>.net.sf.acegisecurity.util.filtertobeanproxy</filter-class>
<init-param>
<param-name>targetclass</param-name>
<param-value>.net.sf.acegisecurity.ui.basicauth.basicprocessingfilter</param-value>
</init-param>
</filter>
<filter>
<filter-name>acegi security system for spring auto integration filter</filter-name>
<filter-class>.net.sf.acegisecurity.ui.autointegrationfilter</filter-class>
</filter>
<filter>
<filter-name>acegi http request security filter</filter-name>
<filter-class>.net.sf.acegisecurity.util.filtertobeanproxy</filter-class>
<init-param>
<param-name>targetclass</param-name>
<param-value>.net.sf.acegisecurity.intercept.web.securityenforcementfilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>acegi channel processing filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>acegi authentication processing filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>acegi http basic authorization filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>acegi security system for spring auto integration filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>acegi http request security filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
create table users (
username varchar(50) not null primary key,
password varchar(50) not null,
enabled bit not null
);
create table authorities (
username varchar(50) not null,
authority varchar(50) not null
);
create unique index ix_auth_username on authorities ( username, authority );
alter table authorities add constraint fk_authorities_users foreign key (username) references users
(username);
<bean id="datasource" class="org.springframework.jdbc.datasource.drivermanagerdatasource">
<property name="driverclassname"><value>${jdbc.driverclassname}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>
<bean id="jdbcdaoimpl" class=".net.sf.acegisecurity.providers.dao.jdbc.jdbcdaoimpl">
<property name="datasource"><ref bean="datasource"/></property>
</bean>
<bean id="daoauthenticationprovider" class=".net.sf.acegisecurity.providers.dao.daoauthenticationprovider">
<property name="authenticationdao"><ref bean="authenticationdao"/></property>
<property name="usercache"><ref bean="usercache"/></property>
</bean>
<bean id="usercache" class=".net.sf.acegisecurity.providers.dao.cache.ehcachebasedusercache">
<property name="minutestoidle"><value>5</value></property>
</bean>
<bean id="authenticationmanager" class=".net.sf.acegisecurity.providers.providermanager">
<property name="providers">
<list>
<ref bean="daoauthenticationprovider"/>
</list>
</property>
</bean>
<bean id="accessdecisionmanager" class=".net.sf.acegisecurity.vote.affirmativebased">
<property name="allowifallabstaindecisions">
<value>false</value>
</property>
<property name="decisionvoters">
<list><ref bean="rolevoter"/></list>
</property>
</bean>
<bean id="rolevoter" class=".net.sf.acegisecurity.vote.rolevoter"/>
<bean id="authenticationprocessingfilterentrypoint"
class=".net.sf.acegisecurity.ui.webapp.authenticationprocessingfilterentrypoint">
<property name="loginformurl"><value>/acegilogin.jsp</value></property>
<property name="forcehttps"><value>false</value></property>
</bean>
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
<%@ page import=".net.sf.acegisecurity.ui.abstractprocessingfilter" %>
<%@ page import=".net.sf.acegisecurity.authenticationexception" %>
<html>
<head>
<title>login</title>
</head>
<body>
<h1>login</h1>
<form action="<c:url value='j_acegi_security_check'/>" method="post">
<table>
<tr><td>user:</td><td><input type='text' name='j_username'></td></tr>
<tr><td>password:</td><td><input type='password' name='j_password'></td></tr>
<tr><td colspan='2'><input name="submit" type="submit"></td></tr>
<tr><td colspan='2'><input name="reset" type="reset"></td></tr>
</table>
</form>
</body>
</html>
<bean id="filterinvocationinterceptor"
class=".net.sf.acegisecurity.intercept.web.filtersecurityinterceptor">
<property name="authenticationmanager">
<ref bean="authenticationmanager"/>
</property>
<property name="accessdecisionmanager">
<ref bean="accessdecisionmanager"/>
</property>
<property name="objectdefinitionsource">
<value>
convert_url_to_lowercase_before_comparison
\a/sec/administrator.*\z=role_supervisor
\a/sec/user.*\z=role_teller
</value>
</property>
</bean>
<bean id="securityenforcementfilter" class=".net.sf.acegisecurity.intercept.web.securityenforcementfilter">
<property name="filtersecurityinterceptor">
<ref bean="filterinvocationinterceptor"/>
</property>
<property name="authenticationentrypoint">
<ref bean="authenticationprocessingfilterentrypoint"/>
</property>
</bean>
<bean id="authenticationprocessingfilter"
class=".net.sf.acegisecurity.ui.webapp.authenticationprocessingfilter">
<property name="authenticationmanager">
<ref bean="authenticationmanager"/>
</property>
<property name="authenticationfailureurl">
<value>/loginerror.jsp</value>
</property>
<property name="defaulttargeturl">
<value>/</value>
</property>
<property name="filterprocessesurl">
<value>/j_acegi_security_check</value>
</property>
</bean>
<bean id="channelprocessingfilter" class=".net.sf.acegisecurity.securechannel.channelprocessingfilter">
<property name="channeldecisionmanager">
<ref bean="channeldecisionmanager"/>
</property>
<property name="filterinvocationdefinitionsource">
<value>
convert_url_to_lowercase_before_comparison
\a/sec/administrator.*\z=requires_secure_channel
\a/acegilogin.jsp.*\z=requires_secure_channel
\a/j_acegi_security_check.*\z=requires_secure_channel
\a.*\z=requires_insecure_channel
</value>
</property>
</bean>
<bean id="channeldecisionmanager" class=".net.sf.acegisecurity.securechannel.channeldecisionmanagerimpl">
<property name="channelprocessors">
<list>
<ref bean="securechannelprocessor"/>
<ref bean="insecurechannelprocessor"/>
</list>
</property>
</bean>
<bean id="securechannelprocessor" class=".net.sf.acegisecurity.securechannel.securechannelprocessor"/>
<bean id="insecurechannelprocessor" class=".net.sf.acegisecurity.securechannel.insecurechannelprocessor"/>
<bean name="/shop/newaccount.do" class="org.springframework.samples.jpetstore.web.spring.accountformcontroller">
<property name="petstore"><ref bean="petstore"/></property>
<property name="validator"><ref bean="accountvalidator"/></property>
<property name="successview"><value>index</value></property>
</bean>
<bean name="/shop/signon.do" class="org.springframework.samples.jpetstore.web.spring.signoncontroller">
<property name="petstore"><ref bean="petstore"/></property>
</bean>
<bean name="/shop/signonform.do" class="org.springframework.web.servlet.mvc.parameterizableviewcontroller">
<property name="viewname"><value>signonform</value></property>
</bean>
<bean id="securehandlermapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping">
<property name="interceptors">
<list>
<ref bean="signoninterceptor"/>
</list>
</property>
<property name="urlmap">
<map>
<entry key="/shop/editaccount.do"><ref local="secure_editaccount"/></entry>
<entry key="/shop/listorders.do"><ref local="secure_listorders"/></entry>
<entry key="/shop/neworder.do"><ref local="secure_neworder"/></entry>
<entry key="/shop/vieworder.do"><ref local="secure_vieworder"/></entry>
</map>
</property>
</bean>
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器