Announcement Announcement Module
Collapse
No announcement yet.
Spring Authentication With DWR Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • I'm quite lost here
    Is there any reason why we can't stick with the old and simpler implementation?
    I thought that it was the right way to go, and also tried to understand why we are still looking for answers..., but i don't really get it
    Keep it up with the good work , i'll try to join you as soon as i understand where we are.
    REgards,

    Comment


    • I'm quite lost here
      Me too

      Is there any reason why we can't stick with the old and simpler implementation?
      Well with the current approach we are duplicating the configuration information necessary to secure methods and to determine whether methods are secure. First we secure the methods using @Security annotations or intercept-methods tags (Or perhaps pointcuts), and then we have to respecify that information when configuring the MethodInvocationPriviligeEvaluator. If we try to support pointcut expressions, then this becomes especially hairy.

      So for example if we use a intercept-methods tag within a bean declaration, we've already told Spring what roles are required to execute a certain method on a specific bean. We should now be able to do isCallable(Object, methodName) without adding further configuration.

      In short we should stick with a DRY process:

      http://en.wikipedia.org/wiki/Don%27t_repeat_yourself

      That will make everything a lot simpler in the long run.

      I thought that it was the right way to go, and also tried to understand why we are still looking for answers..., but i don't really get it
      Another thing is that we are creating and configuring another AccessDecisionManager and voters with our current design (At least with Spring 2.0 / 3.0 when using the security namespace). Spring needs these objects to do the method authorization check, so when I'm configuring them again for the MethodInvocationPrivilegeEvaluator, I'm creating them all over again...

      Keep it up with the good work , i'll try to join you as soon as i understand where we are.
      Diddo! I'm going to attempt to write up some design notes. Hope to have some stuff up soon .

      Comment


      • OK - I think an elegant solution is to create a namespaced AuthorizationService implementation. Something like:

        <security:authorization-service id="authorizationService">

        The bean builder for this would take take care of looking up all the classes that it requires, such as the authentication service, access decision manager, etc. That way these won't have to be duplicated in the configuration file, and it's a lot cleaner.

        Also I think creating the Map<Object, MethodSecurityInterceptor> might not be that difficult (Knock on wood >> my head).

        I'm assuming the following is possible:
        We can assign an ID to to each MethodSecurityInterceptor instance that allows it to be retrieved from the container the same way BeanDefinitionBuilder instances get the default AccessDecisionManager instance from the container.

        We'll have this tag:
        <security:authorization-service id="authorizationService">

        create a Map<Object, MethodSecurityInterceptor> reference handle and corresponding instance. Then the BeanDefinitionParser for the intercept-methods tag will add each object and corresponding MethodSecurityInterceptor to the map (I'm hoping that's possible).

        The the rest should be easy. I'll let you know in a few years if I manage to figure out the namespace stuff

        The thinking here only covers the intercept-methods tag, but I once that's tackled, how to handle pointcuts and security annotations will be much clearer as well.

        Comment


        • It seems that i won't get tired of saying that you are complicating it too much!
          But, if you are happy with it, go on!!

          Regards,

          Comment


          • Yeah! Isn't it fun!! I love talking about stuff when I have no idea what I'm talking about!

            Comment


            • You do have to leave taking those drugs :P

              Comment


              • I'm going to take the coffee IV out as soon as I figure this out

                Comment


                • OK - I've tested this using a ClassPathXmlApplicationContext and it works.

                  Code:
                      <bean
                       id="authorizationServiceImpl"
                       class="com.example.security.authorization.impl.AuthorizationServiceImpl">
                          <property
                           name="methodInvocationPrivilegeEvaluator"
                           ref="methodInvocationPrivilegeEvaluator"/>
                        <property
                            name="secureObjectIDs">
                  		    <set>
                  		        <value>needsAuthorizedMethod</value>
                  		    </set>
                        </property>        
                      </bean>
                  
                      <bean
                       id="needsAuthorizedMethod"
                       class="com.example.protect.NeedsAuthorizedMethod">
                          <security:intercept-methods>
                              <security:protect method="returnString" access="ROLE_ADMIN" />
                          </security:intercept-methods>
                      </bean>
                  Code:
                  	private Set<String> secureObjectIDs;
                  
                  	public Set<String> getSecureObjectIDs() 
                  	{
                  		return secureObjectIDs;
                  	}
                  
                  	public void setSecureObjectIDs(Set<String> secureObjectIDs) 
                  	{
                  		this.secureObjectIDs = secureObjectIDs;
                  	}
                  
                  	public static String METHOD_SECURITY_INTERCEPTOR_ID_POSTFIX = 
                  		"methodSecurityInterceptor";
                  
                  	private Map<Object, MethodSecurityInterceptor> objectToSecureMethodInterceptorMap;
                  	
                  
                  	public void initializeObjectToSecureMethodInterceptorMap(BeanFactory beanFactory)
                  	{
                  		Assert.notNull(this.secureObjectIDs, "In order to use the service configure at least one secure object");		
                  		
                  		objectToSecureMethodInterceptorMap = new HashMap();
                  		
                  		for (String secureObjectID : secureObjectIDs)
                  		{
                  			String methodSecurityInterceptorID = 
                  				secureObjectID
                  				+
                  				"."
                  				+ 
                  				METHOD_SECURITY_INTERCEPTOR_ID_POSTFIX;
                  			
                  			Object object = beanFactory.getBean(secureObjectID);
                  			
                  			//TODO Test what happens when the methodsecurityinterceptor is not present...
                  			//In other words we listed an ID that does not have any secure methods
                  			MethodSecurityInterceptor methodSecurityInterceptor =
                  				(MethodSecurityInterceptor) 
                  				beanFactory.
                  				getBean(methodSecurityInterceptorID);
                  						
                  			if (object != null && methodSecurityInterceptor != null)
                  			{
                  				objectToSecureMethodInterceptorMap.put(object, methodSecurityInterceptor);
                  			}
                  		}
                  	}

                  Code:
                  	public boolean isCallable(Object object, String methodName) throws Exception
                  	{
                  		Authentication authentication = 
                  			SecurityContextHolder.
                  			getContext().
                  			getAuthentication();
                  		
                  		Assert.notNull(object, "DWR remoted Spring bean instance required");
                  
                  		Assert.notNull(this.objectToSecureMethodInterceptorMap, "The map can't be null");
                  		
                  		MethodSecurityInterceptor methodSecurityInterceptor = 
                  			this.objectToSecureMethodInterceptorMap.get(object);
                  		
                  		Assert.notNull(methodSecurityInterceptor, "Could not find MethodSecurityInterceptor instance per the given object key.");
                  
                  		if (methodSecurityInterceptor == null)
                  		{
                  			return false;
                  		}
                  		
                  		MethodInvocation methodInvocation = null;
                  		
                          for(Method method: object.getClass().getMethods())
                          {
                          	if (method.getName().equals(methodName))
                          	{
                          		methodInvocation = new SimpleMethodInvocation(object, method,null);
                          	}
                          }
                          
                          this.
                          getMethodInvocationPrivilegeEvaluator().
                          setSecurityInterceptor(methodSecurityInterceptor);
                          
                          return this.getMethodInvocationPrivilegeEvaluator().
                          		isAllowed(
                          				methodInvocation, 
                          				authentication);		
                  	}
                  In the unit tests I pass the ClassPathXmlApplicationContext instance as the BeanFactory that's necessary to initialize the objectToSecureMethodInterceptorMap reference. So this needs some tweaking in order to make it work in a web context. I think all that's necessary is to lookup the factory like this:

                  ContextLoader.getCurrentWebApplicationContext()

                  I'm going to check that next.

                  Comment


                  • Looks like it's working a little too well...isAllowed returns true regardless of whether the Authentication instance has the required role. Posted a ticket:

                    http://jira.springsource.org/browse/SEC-1198

                    Comment

                    Working...
                    X