Skip to content

Commit

Permalink
Use AuthorizationAnnotationPropertyConversionService
Browse files Browse the repository at this point in the history
Closes gh-15721
  • Loading branch information
jzheaux authored and kse-music committed Sep 4, 2024
2 parents 25ddc2a + b22061d commit ee9254a
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,8 @@ static class DispatcherServletRequestMatcher implements RequestMatcher {
public boolean matches(HttpServletRequest request) {
String name = request.getHttpServletMapping().getServletName();
ServletRegistration registration = this.servletContext.getServletRegistration(name);
Assert.notNull(registration, computeErrorMessage(this.servletContext.getServletRegistrations().values()));
Assert.notNull(registration,
() -> computeErrorMessage(this.servletContext.getServletRegistrations().values()));
try {
Class<?> clazz = Class.forName(registration.getClassName());
return DispatcherServlet.class.isAssignableFrom(clazz);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,14 @@ public void adviseWhenPrePostEnabledThenEachInterceptorRunsExactlyOnce() {
verify(expressionHandler, times(4)).createEvaluationContext(any(Supplier.class), any());
}

@Test
@WithMockUser(roles = "uid")
public void methodWhenMetaAnnotationPropertiesHasClassProperties() {
this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
assertThat(service.getIdPath("uid")).isEqualTo("uid");
}

private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
}
Expand Down Expand Up @@ -1376,6 +1384,23 @@ List<String> resultsContainDave(List<String> list) {
return list;
}

@RestrictedAccess(entityClass = EntityClass.class)
String getIdPath(String id) {
return id;
}

}

@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasRole({idPath})")
@interface RestrictedAccess {

String idPath() default "#id";

Class<?> entityClass();

String[] recipes() default {};

}

@Retention(RetentionPolicy.RUNTIME)
Expand All @@ -1386,6 +1411,10 @@ List<String> resultsContainDave(List<String> list) {

}

static class EntityClass {

}

@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasAuthority('SCOPE_{claim}') || hasAnyRole({roles})")
@interface HasClaim {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.authorization.method;

import java.util.Collections;
import java.util.Set;

import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;

/**
* A {@link ConversionService} configured with converters that provide class to string
* conversion
*
* @author DingHao
* @since 6.3
*/
public final class AuthorizationAnnotationPropertyConversionService extends GenericConversionService {

private static volatile AuthorizationAnnotationPropertyConversionService sharedInstance;

private AuthorizationAnnotationPropertyConversionService() {
addConverters(this);
}

/**
* Returns a shared instance of
* {@code AuthorizationAnnotationPropertyConversionService}.
* @return a shared instance of
* {@code AuthorizationAnnotationPropertyConversionService}
*/
public static AuthorizationAnnotationPropertyConversionService getSharedInstance() {
AuthorizationAnnotationPropertyConversionService cs = sharedInstance;
if (cs == null) {
synchronized (AuthorizationAnnotationPropertyConversionService.class) {
cs = sharedInstance;
if (cs == null) {
cs = new AuthorizationAnnotationPropertyConversionService();
sharedInstance = cs;
}
}
}
return cs;
}

/**
* Adds the converters that provide type conversion for
* AuthorizationAnnotationProperty values to the provided {@link ConverterRegistry}.
* @param converterRegistry the registry of converters to add to
*/
public static void addConverters(ConverterRegistry converterRegistry) {
DefaultConversionService.addDefaultConverters(converterRegistry);
converterRegistry.addConverter(new ClassToStringConverter());
}

static class ClassToStringConverter implements GenericConverter {

@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Class.class, String.class));
}

@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
return (source != null) ? source.toString() : null;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.core.annotation.RepeatableContainers;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.util.PropertyPlaceholderHelper;

/**
Expand Down Expand Up @@ -70,7 +69,8 @@ static <A extends Annotation> Function<AnnotatedElement, A> withDefaults(Class<A
String key = property.getKey();
Object value = property.getValue();
String asString = (value instanceof String) ? (String) value
: DefaultConversionService.getSharedInstance().convert(value, String.class);
: AuthorizationAnnotationPropertyConversionService.getSharedInstance()
.convert(value, String.class);
stringProperties.put(key, asString);
}
AnnotatedElement annotatedElement = (AnnotatedElement) mergedAnnotation.getSource();
Expand Down

0 comments on commit ee9254a

Please sign in to comment.