@Test public void methodsWithDifferentArgumentsAreMatchedCorrectly() throws Exception { mds.addSecureMethod(MockService.class, someMethodInteger, ROLE_A); mds.addSecureMethod(MockService.class, someMethodString, ROLE_B); assertThat(mds.getAttributes(someMethodInteger, MockService.class)).isEqualTo(ROLE_A); assertThat(mds.getAttributes(someMethodString, MockService.class)).isEqualTo(ROLE_B); }
/** * Add configuration attributes for a secure method. Mapped method names can end or start with * <code>*</code> for matching multiple methods. * * @param javaType target interface or class the security configuration attribute applies to * @param mappedName mapped method name, which the javaType has declared or inherited * @param attr required authorities associated with the method */ public void addSecureMethod(Class<?> javaType, String mappedName, List<ConfigAttribute> attr) { String name = javaType.getName() + '.' + mappedName; if (logger.isDebugEnabled()) { logger.debug("Request to add secure method [" + name + "] with attributes [" + attr + "]"); } Method[] methods = javaType.getMethods(); List<Method> matchingMethods = new ArrayList<Method>(); for (Method m : methods) { if (m.getName().equals(mappedName) || isMatch(m.getName(), mappedName)) { matchingMethods.add(m); } } if (matchingMethods.isEmpty()) { throw new IllegalArgumentException( "Couldn't find method '" + mappedName + "' on '" + javaType + "'"); } // register all matching methods for (Method method : matchingMethods) { RegisteredMethod registeredMethod = new RegisteredMethod(method, javaType); String regMethodName = (String) this.nameMap.get(registeredMethod); if ((regMethodName == null) || (!regMethodName.equals(name) && (regMethodName.length() <= name.length()))) { // no already registered method name, or more specific // method name specification now -> (re-)register method if (regMethodName != null) { logger.debug( "Replacing attributes for secure method [" + method + "]: current name [" + name + "] is more specific than [" + regMethodName + "]"); } this.nameMap.put(registeredMethod, name); addSecureMethod(registeredMethod, attr); } else { logger.debug( "Keeping attributes for secure method [" + method + "]: current name [" + name + "] is not more specific than [" + regMethodName + "]"); } } }
/** * Add configuration attributes for a secure method. Method names can end or start with <code>* * </code> for matching multiple methods. * * @param name type and method name, separated by a dot * @param attr the security attributes associated with the method */ private void addSecureMethod(String name, List<ConfigAttribute> attr) { int lastDotIndex = name.lastIndexOf("."); if (lastDotIndex == -1) { throw new IllegalArgumentException( "'" + name + "' is not a valid method name: format is FQN.methodName"); } String methodName = name.substring(lastDotIndex + 1); Assert.hasText(methodName, "Method not found for '" + name + "'"); String typeName = name.substring(0, lastDotIndex); Class<?> type = ClassUtils.resolveClassName(typeName, this.beanClassLoader); addSecureMethod(type, methodName, attr); }
/** * Creates the <tt>MapBasedMethodSecurityMetadataSource</tt> from a * * @param methodMap map of method names to <tt>ConfigAttribute</tt>s. */ public MapBasedMethodSecurityMetadataSource(Map<String, List<ConfigAttribute>> methodMap) { for (Map.Entry<String, List<ConfigAttribute>> entry : methodMap.entrySet()) { addSecureMethod(entry.getKey(), entry.getValue()); } }
@Test public void wildcardedMatchIsOverwrittenByMoreSpecificMatch() { mds.addSecureMethod(MockService.class, "some*", ROLE_A); mds.addSecureMethod(MockService.class, "someMethod*", ROLE_B); assertThat(mds.getAttributes(someMethodInteger, MockService.class)).isEqualTo(ROLE_B); }