acegi ref 1.4~1.5

1.4 REQUEST CONTEXTS
1.4.Historical Approach
 
在0.9.0版本前,Acegi Security使用ContextHolder来存储一个Context在sessions间。Context一个特殊的子类,SecureContext定义了一个接口用来存储Authentication对象。The
ContextHolder was a ThreadLocal.在与其他sping开发人员讨论后为了一致性,决定将这个在0.9.0版后中被移出。见例子http://article.gmane.org/gmane.comp.java.springframework.devel/8290.
提起ContextHolder这些历史是由于我们在以后的文档中也许还会提到它。一般来说你应该用SecurityContextHolder替代ContextHolder.用SecurityContext替代SecureContext,你将获得这些文档的主要的意思primary meaning。
 
1.4.2 SecurityContext
Acegi Security System 使用SecurityContextHolder存储SecurityContext。SecurityContext为Authentication提供getter setter方法。所有的Acegi Security类请求SecurityContextHolder来获得一个当前的SecurityContext(and in turn the principal).。
SecurityContextHolde 是一个可继承的ThreadLocal(InheritableThreadLocal),意思是它是一个当前执行进程的关联。
 
1.4.3Context Storage
 
Acegi Security的中心设计是SecurityContextHolder的内容能在web request间存储。因为这样,通过将Authentication存储在一个从SecurityContextHolder获得的SecurityContext中,一个成功认证的principal在并发请求情况下被鉴别。现有的HttpSessionContextIntegrationFilter能自动将一个定义良好的HttpSession属性内容拷贝入SecurityContextHolder,接着在各个请求的结束时,将SecurityContextHolder拷贝回HttpSession为下一个请求做准备。
 
对于最终用户,一个本质的,极其普遍的错误是将HttpSessionContextIntegrationFilter出现在其他Acegi Security过滤器的前面。Acegi Security过滤器期望能修改SecurityContextHolder内容,以便成为与他们合适的as they see fit, and something else。这就是为什么HttpSessionContextIntegrationFilter必须是第一个过滤器。你可以定义一个自定义的SecurityContext实现,并通过设置在HttpSessionContextIntegrationFilter Bean 中的context属性把它使用在你的应用程序中。
1.5.安全拦截器
 
1.5.1所有安全对象
 
正如在高层设计节描述的,每个安全对象有自己的拦截器,负责处理各自的请求。处理包括一系列操作:
1.   保存与每个安全请求相关联的配置属性
2.   从ObjectDefinitionSource取出与请求相关的ConfigAttributeDefinition
3.   从SecureContext中获得Authentication对象,SecureContext储存在ContextHolder中
4.   将Authentication对象传递给AuthenticationManager,更新ContextHolder(update the ContextHolder with the response.)
5. 将Authentication对象,ConfigAttributeDefinition和安全对象传递给AccessDecisionManager
6. 将Authentication对象,ConfigAttributeDefinition和安全对象传递给RunAsManager
7. 如果RunAsManager返回一个新的Authentication对象,将其更新入ContextHold
8. 处理这个安全对象的执行请求
9. If the RunAsManager earlier returned a new Authentication object, update the ContextHolder with the Authentication object that was previously returned by the AuthenticationManager.
10.              如果一个AfterInvocationManager被定义了,pass it the result of the secure object execution so that it may throw an AccessDeniedException or mutate the returned object if required.
11. Return any result received from the AfterInvocationManager, or if no AfterInvocationManager is defined, simply return the result provided by the secure object execution.
 
这里同时出现了很多内容,不要担心。开发人员只需要简单的执行基本的接口(AccessDecisionManager),下面将详细讨论。
 
AbstractSecurityInterceptor处理以上列表的主要内容。正如图一,每个安全对象有自己的安全拦截器,他们都是AbstractSecurityInterceptor的子类,下面讨论。
 
1.5.2 AOP Alliance(MethodInvocation)安全拦截器
为了方法调用的安全,开发人员只要在应用程序内简单的添加MethodSecurityInterceptor
的适当的配置即可。这个bean所需的安全被链接入这个拦截器。Next the beans requiring security are chained into the interceptor. This chaining is accomplished using Spring’s ProxyFactoryBean or BeanNameAutoProxyCreator, as commonly used by many other parts of Spring (refer to the sample application for examples).
另外,acegi 提供了一个MethodDefinitionSourceAdvisor,它可能被用于DefaultAdvisorAutoProxyCreator,以便在any beans defined against the
MethodSecurityInterceptor.前自动的链接安全拦截器。
 
 
 
 
The MethodSecurityInterceptor itself is configured as follows:
 
<bean id="bankManagerSecurity"
class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="validateConfigAttributes"><value>true</value></property>
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
<property name="runAsManager"><ref bean="runAsManager"/></property>
<property name="afterInvocationManager"><ref bean="afterInvocationManager"/></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_AS_SERVER
</value>
</property>
</bean>
 
其中涉及到的bean的引用接下来将详细讲解。AfterInvocationManager,这是完全可选的。
A full discussion of configuration attributes is provided in the High Level Design section of
this document.
MethodSecurityInterceptor的属性配置可以通过三种方式。
The first is via a property editor and the application context,which is shown above.
The second is via defining the configuration attributes in your source code using Jakarta Commons Attributes or Java 5 Annotations.
The third is via writing your own ObjectDefinitionSource, although this is beyond the scope of this document.
 
不管如何实现 the ObjectDefinitionSource is responsible for returning a ConfigAttributeDefinition object that contains all of the configuration attributes associated with a single secure method.
 
需要注意的是MethodSecurityInterceptor.setObjectDefinitionSource()方法真实需要的是一个MethodDefinitionSource实例,这是一个ObjectDefinitionSource的子类。这意味着ObjectDefinitionSource理解MethodInvocations.
 
如果使用application context property editor approach,正如上面代码所显示的。逗号被用来分割不同的配置属性。每个配置属性被设置进它自己的SecurityConfig对象。
如果你使用Jakarta Commons Attributes approach,,你的bean 内容将做不同的配置
<bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/>
<bean id="objectDefinitionSource"
class="net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes">
<property name="attributes"><ref local="attributes"/></property>
</bean>
<bean id="bankManagerSecurity"
class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
<property name="validateConfigAttributes"><value>false</value></property>
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
<property name="runAsManager"><ref bean="runAsManager"/></property>
<property name="objectDefinitionSource"><ref bean="objectDefinitionSource"/></property>
</bean>
 
另外,我的原代码将包含Jakarta Commons Attributes tags
 
public interface BankManager {
/**
* @@SecurityConfig("ROLE_SUPERVISOR")
* @@SecurityConfig("RUN_AS_SERVER")
*/
public void deleteSomething(int id);
/**
* @@SecurityConfig("ROLE_SUPERVISOR")
* @@SecurityConfig("RUN_AS_SERVER")
*/
public void deleteAnother(int id);
/**
* @@SecurityConfig("ROLE_TELLER")
* @@SecurityConfig("ROLE_SUPERVISOR")
* @@SecurityConfig("BANKSECURITY_CUSTOMER")
* @@SecurityConfig("RUN_AS_SERVER")
*/
public float getBalance(int id);
}
 
 
 
 
 
 
If you are using the Spring Security Java 5 Annotations approach, your bean context will be configured as follows:
<bean id="attributes" class="net.sf.acegisecurity.annotation.SecurityAnnotationAttributes"/>
<bean id="objectDefinitionSource"
class="net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes">
<property name="attributes"><ref local="attributes"/></property>
</bean>
<bean id="bankManagerSecurity"
class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
<property name="validateConfigAttributes"><value>false</value></property>
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
<property name="runAsManager"><ref bean="runAsManager"/></property>
<property name="objectDefinitionSource"><ref bean="objectDefinitionSource"/></property>
</bean>
 
 
In addition, your source code will contain the Acegi Java 5 Security Annotations that represent the ConfigAttribute. The following example uses the @Secured annotations to represent the configuration attributes, and results in the same security configuration as provided by the property editor approach:
import net.sf.acegisecurity.annotation.Secured;
public interface BankManager {
/**
* Delete something
*/
@Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" })
public void deleteSomething(int id);
/**
* Delete another
*/
@Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" })
public void deleteAnother(int id);
/**
* Get balance
*/
@Secured({"ROLE_TELLER","ROLE_SUPERVISOR","BANKSECURITY_CUSTOMER","RUN_AS_SERVER" })
public float getBalance(int id);
}
validateConfigAttributes 当将这个值设为ture ,将在开始的时候评估这个配置属性是否有效。
 
1.5.3 AspectJ (JoinPoint) Security Interceptor
AspectJ安全拦截器与上一节讨论到的AOP Alliance security interceptor相似。所以我们在这只讨论他们的不同之处。
 
AspectJ拦截器的名字是AspectJSecurityInterceptor。不同于AOP Alliance security interceptor依赖于Spring组织安全拦截通过proxying,AspectJSecurityInterceptor通过AspectJ编译器。同时使用不同类型的安全拦截器在同一个应用中是不太常见的,例如AspectJSecurityInterceptor用于域对象实例的安全,
AOP Alliance MethodSecurityInterceptor用于业务逻辑层的的安全
 
下面来考虑如何配置AspectJSecurityInterceptor如何配置的
<bean id="bankManagerSecurity"
class="net.sf.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor">
<property name="validateConfigAttributes"><value>true</value></property>
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
<property name="runAsManager"><ref bean="runAsManager"/></property>
<property name="afterInvocationManager"><ref bean="afterInvocationManager"/></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_AS_SERVER
</value>
</property>
</bean>
 
正如你所看到的,除了类名不同,AspectJSecurityInterceptor和AOP Alliance安全拦截器极其相似。事实上这两个拦截器可以共享相同的objectDefinitionSource,因为ObjectDefinitionSource工作的库为java.lang.reflect.Methods,而不需要AOP library-specific class. Of course, your access decisions have access to the relevant AOP library-specific invocation (ie MethodInvocation or JoinPoint) and as such can consider a range of addition criteria when making access decisions (such as method arguments).
 
 
接下来你需要定义AspectJ aspect。例如:
package net.sf.acegisecurity.samples.aspectj;
import net.sf.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor;
import net.sf.acegisecurity.intercept.method.aspectj.AspectJCallback;
import org.springframework.beans.factory.InitializingBean;
public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
private AspectJSecurityInterceptor securityInterceptor;
pointcut domainObjectInstanceExecution(): target(PersistableEntity)
&& execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect);
Object around(): domainObjectInstanceExecution() {
if (this.securityInterceptor != null) {
AspectJCallback callback = new AspectJCallback() {
public Object proceedWithObject() {
return proceed();
}
};
return this.securityInterceptor.invoke(thisJoinPoint, callback);
} else {
return proceed();
}
}
public AspectJSecurityInterceptor getSecurityInterceptor() {
return securityInterceptor;
}
public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
this.securityInterceptor = securityInterceptor;
}
public void afterPropertiesSet() throws Exception {
if (this.securityInterceptor == null)
throw new IllegalArgumentException("securityInterceptor required");
}
}
在上面的例子中安全拦截器将被应用到每个PersistableEntity的实例,你可以使用任何其他类或者pointcut表达式。AspectJCallback是必须的,因为proceed();statement has special meaning only within an around() body。The AspectJSecurityInterceptor calls this anonymous AspectJCallback class when it wants the target object to continue.
 
你将需要配置Spring来加载aspect,and wire it with the AspectJSecurityInterceptor.
A
bean declaration which achieves this is shown below:
<bean id="domainObjectInstanceSecurityAspect"
class="net.sf.acegisecurity.samples.aspectj.DomainObjectInstanceSecurityAspect"
factory-method="aspectOf">
<property name="securityInterceptor"><ref bean="aspectJSecurityInterceptor"/></property>
</bean>
That's it! Now you can create your beans from anywhere within your application, using whatever means you think fit (eg new Person();) and they will have the security interceptor applied.
 
1.5.4 FilterInvocation Security Interceptor
 
为了保护FilterInvocations ,开发人员需要向web.xml中添加filter来委派到SecurityEnforcementFilter,一个典型的配置实例如下:
<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 HTTP Request Security Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
 
注意到这个过滤器实际上是FilterToBeanProxy,大多数被Acegi Security System
for Spring 使用的过滤器都使用这个类。可以查阅Filters节来学习关于这个bean更多的知识。
 
在这个应用中你将需要配置三个bean:
 
<bean id="securityEnforcementFilter"
class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
<property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
<property name="authenticationEntryPoint"><ref bean="authenticationEntryPoint"/></property>
</bean>
<bean id="authenticationEntryPoint"
class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl"><value>/acegilogin.jsp</value></property>
<property name="forceHttps"><value>false</value></property>
</bean>
<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="runAsManager"><ref bean="runAsManager"/></property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
/A/secure/super/.*/Z=ROLE_WE_DONT_HAVE
/A/secure/.*/Z=ROLE_SUPERVISOR,ROLE_TELLER
</value>
</property>
</bean>
 
如果用户请求一个受保护的HTTP资源但是没有被认证,AuthenticationEntryPoint将被调用。这个类处理这个请求,将合适的响应返回给用户,以便他们开始认证。Acegi Security System for Spring提供了三个实现类:AuthenticationProcessingFilterEntryPoint 开始基于form的认证
BasicProcessingFilterEntryPoint 开始基于HTTP BASIC 认证过程
CasProcessingFilterEntryPoint 开始基于Yale Central Authentication Service (CAS) login.
 
AuthenticationProcessingFilterEntryPoint,CasProcessingFilterEntryPoint有可选的属性,可以强制使用HTTPS,请参考JAVAdoc.
 
portMapper提供信息,哪些http端口相应的https端口,这个用于AuthenticationProcessingFilterEntryPoint以及其他bean。默认执行PortMappingImpl, knows the common HTTP ports 80 and 8080 map to HTTPS ports 443 and 8443 respectively.
你可以按需求自定义。
 
SecurityEnforcementFilter主要提供session管理支持以及开始认证。它代理了真实的FilterInvocation安全决策 to the configured FilterSecurityInterceptor.
 
与其他安全拦截器类似,FilterSecurityInterceptor需要引用AuthenticationManager, AccessDecisionManager and RunAsManager,。有两种方法配置属性,
The first is via a property editor and the application context,
The second is via writing your own ObjectDefinitionSource, although this is beyond the scope of this document.
 
It should be noted that the FilterSecurityInterceptor.setObjectDefinitionSource() method actually expects an instance of FilterInvocationDefinitionSource. This is a marker interface which subclasses ObjectDefinitionSource. It simply denotes the ObjectDefinitionSource understands FilterInvocations. In the interests of simplicity we'll continue to refer to the FilterInvocationDefinitionSource as an
ObjectDefinitionSource, as the distinction is of little relevance to most users of the
FilterSecurityInterceptor.
 
The default is to treat all expressions as regular expressions.
Alternatively, the presence of a PATTERN_TYPE_APACHE_ANT directive will cause all expressions to be treated as Apache Ant paths. It is not possible to mix expression syntaxes within the same definition. For example, the earlier configuration could be generated using Apache Ant paths as follows:
 
<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="runAsManager"><ref bean="runAsManager"/></property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/secure/super/**=ROLE_WE_DONT_HAVE
/secure/**=ROLE_SUPERVISOR,ROLE_TELLER
</value>
</property>
</bean>
Irrespective of the type of expression syntax used, expressions are always evaluated in the order they are defined. Thus it is important that more specific expressions are defined higher in the list than less specific expressions.
越特殊的表达示放在越前面。
The special keyword CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON causes the
FilterInvocationDefinitionSource to automatically convert a request URL to lowercase before comparison against the expressions. Whilst by default the case of the request URL is not converted, it is generally recommended to use CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON and write each expression assuming
lowercase.As with other security interceptors, the validateConfigAttributes property is observed. When set to true (the default), at startup time the FilterSecurityInterceptor will evaluate if the provided configuration attributes are valid. It does this by checking each configuration attribute can be processed by either the AccessDecisionManager or the RunAsManager. If neither of these can process a given configuration attribute, an exception is thrown.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值