secured-objects.xml 8.1 KB

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