secured-objects.xml 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="secure-object-impls"
  2. xmlns:xlink="http://www.w3.org/1999/xlink">
  3. <info>
  4. <title>Secure Object Implementations</title>
  5. </info>
  6. <section xml:id="aop-alliance">
  7. <info>
  8. <title>AOP Alliance (MethodInvocation) Security Interceptor</title>
  9. </info>
  10. <para> Prior to Spring Security 2.0, securing <classname>MethodInvocation</classname>s
  11. needed quite a lot of boiler plate configuration. Now the recommended approach for
  12. method security is to use <link xlink:href="#ns-method-security">namespace
  13. configuration</link>. This way the method security infrastructure beans are configured
  14. automatically for you so you don't really need to know about the implementation classes.
  15. We'll just provide a quick overview of the classes that are involved here. </para>
  16. <para> Method security in enforced using a <classname>MethodSecurityInterceptor</classname>,
  17. which secures <classname>MethodInvocation</classname>s. Depending on the configuration
  18. approach, an interceptor may be specific to a single bean or shared between multiple
  19. beans. The interceptor uses a
  20. <interfacename>MethodSecurityMetadataSource</interfacename> instance to obtain the
  21. configuration attributes that apply to a particular method invocation.
  22. <classname>MapBasedMethodSecurityMetadataSource</classname> is used to store
  23. configuration attributes keyed by method names (which can be wildcarded) and will be
  24. used internally when the attributes are defined in the application context using the
  25. <literal>&lt;intercept-methods&gt;</literal> or <literal>&lt;protect-point&gt;</literal>
  26. elements. Other implementations will be used to handle annotation-based configuration. </para>
  27. <section>
  28. <title>Explicit MethodSecurityInterceptor Configuration</title>
  29. <para> You can of course configure a <classname>MethodSecurityIterceptor</classname>
  30. directly in your application context for use with one of Spring AOP's proxying
  31. mechanisms: <programlisting language="xml"><![CDATA[
  32. <bean id="bankManagerSecurity" class=
  33. "org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
  34. <property name="authenticationManager" ref="authenticationManager"/>
  35. <property name="accessDecisionManager" ref="accessDecisionManager"/>
  36. <property name="afterInvocationManager" ref="afterInvocationManager"/>
  37. <property name="securityMetadataSource">
  38. <sec:method-security-metadata-source>
  39. <sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/>
  40. <sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/>
  41. </sec:method-security-metadata-source>
  42. </property>
  43. </bean> ]]>
  44. </programlisting></para>
  45. </section>
  46. </section>
  47. <section xml:id="aspectj">
  48. <info>
  49. <title>AspectJ (JoinPoint) Security Interceptor</title>
  50. </info>
  51. <para>The AspectJ security interceptor is very similar to the AOP Alliance security
  52. interceptor discussed in the previous section. Indeed we will only discuss the
  53. differences in this section.</para>
  54. <para>The AspectJ interceptor is named <literal>AspectJSecurityInterceptor</literal>. Unlike
  55. the AOP Alliance security interceptor, which relies on the Spring application context to
  56. weave in the security interceptor via proxying, the
  57. <literal>AspectJSecurityInterceptor</literal> is weaved in via the AspectJ compiler. It
  58. would not be uncommon to use both types of security interceptors in the same
  59. application, with <literal>AspectJSecurityInterceptor</literal> being used for domain
  60. object instance security and the AOP Alliance
  61. <classname>MethodSecurityInterceptor</classname> being used for services layer
  62. security.</para>
  63. <para>Let's first consider how the <literal>AspectJSecurityInterceptor</literal> is
  64. configured in the Spring application context:</para>
  65. <programlisting language="xml"><![CDATA[
  66. <bean id="bankManagerSecurity" class=
  67. "org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
  68. <property name="authenticationManager" ref="authenticationManager"/>
  69. <property name="accessDecisionManager" ref="accessDecisionManager"/>
  70. <property name="afterInvocationManager" ref="afterInvocationManager"/>
  71. <property name="securityMetadataSource">
  72. <sec:method-security-metadata-source>
  73. <sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/>
  74. <sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/>
  75. </sec:method-security-metadata-source>
  76. </property>
  77. </bean>]]> </programlisting>
  78. <para>As you can see, aside from the class name, the
  79. <literal>AspectJSecurityInterceptor</literal> is exactly the same as the AOP Alliance
  80. security interceptor. Indeed the two interceptors can share the same
  81. <literal>securityMetadataSource</literal>, as the
  82. <interfacename>SecurityMetadataSource</interfacename> works with
  83. <literal>java.lang.reflect.Method</literal>s rather than an AOP library-specific class.
  84. Of course, your access decisions have access to the relevant AOP library-specific
  85. invocation (ie <classname>MethodInvocation</classname> or <literal>JoinPoint</literal>)
  86. and as such can consider a range of addition criteria when making access decisions (such
  87. as method arguments).</para>
  88. <para>Next you'll need to define an AspectJ <literal>aspect</literal>. For example:</para>
  89. <programlisting language="java">
  90. package org.springframework.security.samples.aspectj;
  91. import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
  92. import org.springframework.security.access.intercept.aspectj.AspectJCallback;
  93. import org.springframework.beans.factory.InitializingBean;
  94. public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
  95. private AspectJSecurityInterceptor securityInterceptor;
  96. pointcut domainObjectInstanceExecution(): target(PersistableEntity)
  97. &amp;&amp; execution(public * *(..)) &amp;&amp; !within(DomainObjectInstanceSecurityAspect);
  98. Object around(): domainObjectInstanceExecution() {
  99. if (this.securityInterceptor == null) {
  100. return proceed();
  101. }
  102. AspectJCallback callback = new AspectJCallback() {
  103. public Object proceedWithObject() {
  104. return proceed();
  105. }
  106. };
  107. return this.securityInterceptor.invoke(thisJoinPoint, callback);
  108. }
  109. public AspectJSecurityInterceptor getSecurityInterceptor() {
  110. return securityInterceptor;
  111. }
  112. public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
  113. this.securityInterceptor = securityInterceptor;
  114. }
  115. public void afterPropertiesSet() throws Exception {
  116. if (this.securityInterceptor == null)
  117. throw new IllegalArgumentException("securityInterceptor required");
  118. }
  119. }
  120. }
  121. </programlisting>
  122. <para>In the above example, the security interceptor will be applied to every instance of
  123. <literal>PersistableEntity</literal>, which is an abstract class not shown (you can use
  124. any other class or <literal>pointcut</literal> expression you like). For those curious,
  125. <literal>AspectJCallback</literal> is needed because the <literal>proceed();</literal>
  126. statement has special meaning only within an <literal>around()</literal> body. The
  127. <literal>AspectJSecurityInterceptor</literal> calls this anonymous
  128. <literal>AspectJCallback</literal> class when it wants the target object to
  129. continue.</para>
  130. <para>You will need to configure Spring to load the aspect and wire it with the
  131. <literal>AspectJSecurityInterceptor</literal>. A bean declaration which achieves this is
  132. shown below:</para>
  133. <programlisting language="xml"><![CDATA[
  134. <bean id="domainObjectInstanceSecurityAspect"
  135. class="security.samples.aspectj.DomainObjectInstanceSecurityAspect"
  136. factory-method="aspectOf">
  137. <property name="securityInterceptor" ref="bankManagerSecurity"/>
  138. </bean>]]>
  139. </programlisting>
  140. <para>That's it! Now you can create your beans from anywhere within your application, using
  141. whatever means you think fit (eg <literal>new Person();</literal>) and they will have
  142. the security interceptor applied.</para>
  143. </section>
  144. </chapter>