Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
kse-music committed Jan 22, 2024
1 parent 6df9ef5 commit f0516e0
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* 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.
Expand Down Expand Up @@ -44,6 +44,7 @@
*
* @author Evgeniy Cheban
* @author Josh Cummings
* @author DingHao
* @since 5.6
*/
public final class Jsr250AuthorizationManager implements AuthorizationManager<MethodInvocation> {
Expand Down Expand Up @@ -121,7 +122,7 @@ AuthorizationManager<MethodInvocation> resolveManager(Method method, Class<?> ta
private Annotation findJsr250Annotation(Method method, Class<?> targetClass) {
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
Annotation annotation = findAnnotation(specificMethod);
return (annotation != null) ? annotation : findAnnotation(specificMethod.getDeclaringClass());
return (annotation != null) ? annotation : findAnnotation(targetClass);
}

private Annotation findAnnotation(Method method) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* 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.
Expand Down Expand Up @@ -31,6 +31,7 @@
* For internal use only, as this contract is likely to change.
*
* @author Evgeniy Cheban
* @author DingHao
* @since 5.8
*/
final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
Expand All @@ -54,7 +55,7 @@ MethodSecurityExpressionHandler getExpressionHandler() {
@Override
ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
PostAuthorize postAuthorize = findPostAuthorizeAnnotation(specificMethod);
PostAuthorize postAuthorize = findPostAuthorizeAnnotation(specificMethod, targetClass);
if (postAuthorize == null) {
return ExpressionAttribute.NULL_ATTRIBUTE;
}
Expand All @@ -63,10 +64,10 @@ ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
return new ExpressionAttribute(postAuthorizeExpression);
}

private PostAuthorize findPostAuthorizeAnnotation(Method method) {
private PostAuthorize findPostAuthorizeAnnotation(Method method, Class<?> targetClass) {
PostAuthorize postAuthorize = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PostAuthorize.class);
return (postAuthorize != null) ? postAuthorize
: AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), PostAuthorize.class);
: AuthorizationAnnotationUtils.findUniqueAnnotation(targetClass, PostAuthorize.class);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* 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.
Expand Down Expand Up @@ -30,6 +30,7 @@
* For internal use only, as this contract is likely to change.
*
* @author Evgeniy Cheban
* @author DingHao
* @since 5.8
*/
final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
Expand All @@ -53,7 +54,7 @@ MethodSecurityExpressionHandler getExpressionHandler() {
@Override
ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
PostFilter postFilter = findPostFilterAnnotation(specificMethod);
PostFilter postFilter = findPostFilterAnnotation(specificMethod, targetClass);
if (postFilter == null) {
return ExpressionAttribute.NULL_ATTRIBUTE;
}
Expand All @@ -62,10 +63,10 @@ ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
return new ExpressionAttribute(postFilterExpression);
}

private PostFilter findPostFilterAnnotation(Method method) {
private PostFilter findPostFilterAnnotation(Method method, Class<?> targetClass) {
PostFilter postFilter = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PostFilter.class);
return (postFilter != null) ? postFilter
: AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), PostFilter.class);
: AuthorizationAnnotationUtils.findUniqueAnnotation(targetClass, PostFilter.class);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* 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.
Expand Down Expand Up @@ -31,6 +31,7 @@
* For internal use only, as this contract is likely to change.
*
* @author Evgeniy Cheban
* @author DingHao
* @since 5.8
*/
final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
Expand Down Expand Up @@ -58,7 +59,7 @@ MethodSecurityExpressionHandler getExpressionHandler() {
@Override
ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
PreAuthorize preAuthorize = findPreAuthorizeAnnotation(specificMethod);
PreAuthorize preAuthorize = findPreAuthorizeAnnotation(specificMethod, targetClass);
if (preAuthorize == null) {
return ExpressionAttribute.NULL_ATTRIBUTE;
}
Expand All @@ -67,10 +68,10 @@ ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
return new ExpressionAttribute(preAuthorizeExpression);
}

private PreAuthorize findPreAuthorizeAnnotation(Method method) {
private PreAuthorize findPreAuthorizeAnnotation(Method method, Class<?> targetClass) {
PreAuthorize preAuthorize = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PreAuthorize.class);
return (preAuthorize != null) ? preAuthorize
: AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), PreAuthorize.class);
: AuthorizationAnnotationUtils.findUniqueAnnotation(targetClass, PreAuthorize.class);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* 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.
Expand Down Expand Up @@ -30,6 +30,7 @@
* For internal use only, as this contract is likely to change.
*
* @author Evgeniy Cheban
* @author DingHao
* @since 5.8
*/
final class PreFilterExpressionAttributeRegistry
Expand All @@ -54,7 +55,7 @@ MethodSecurityExpressionHandler getExpressionHandler() {
@Override
PreFilterExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
PreFilter preFilter = findPreFilterAnnotation(specificMethod);
PreFilter preFilter = findPreFilterAnnotation(specificMethod, targetClass);
if (preFilter == null) {
return PreFilterExpressionAttribute.NULL_ATTRIBUTE;
}
Expand All @@ -63,10 +64,10 @@ PreFilterExpressionAttribute resolveAttribute(Method method, Class<?> targetClas
return new PreFilterExpressionAttribute(preFilterExpression, preFilter.filterTarget());
}

private PreFilter findPreFilterAnnotation(Method method) {
private PreFilter findPreFilterAnnotation(Method method, Class<?> targetClass) {
PreFilter preFilter = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PreFilter.class);
return (preFilter != null) ? preFilter
: AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), PreFilter.class);
: AuthorizationAnnotationUtils.findUniqueAnnotation(targetClass, PreFilter.class);
}

static final class PreFilterExpressionAttribute extends ExpressionAttribute {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* 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.
Expand Down Expand Up @@ -41,6 +41,7 @@
* contains a specified authority from the Spring Security's {@link Secured} annotation.
*
* @author Evgeniy Cheban
* @author DingHao
* @since 5.6
*/
public final class SecuredAuthorizationManager implements AuthorizationManager<MethodInvocation> {
Expand Down Expand Up @@ -86,14 +87,14 @@ private Set<String> getAuthorities(MethodInvocation methodInvocation) {

private Set<String> resolveAuthorities(Method method, Class<?> targetClass) {
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
Secured secured = findSecuredAnnotation(specificMethod);
Secured secured = findSecuredAnnotation(specificMethod, targetClass);
return (secured != null) ? Set.of(secured.value()) : Collections.emptySet();
}

private Secured findSecuredAnnotation(Method method) {
private Secured findSecuredAnnotation(Method method, Class<?> targetClass) {
Secured secured = AuthorizationAnnotationUtils.findUniqueAnnotation(method, Secured.class);
return (secured != null) ? secured
: AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), Secured.class);
: AuthorizationAnnotationUtils.findUniqueAnnotation(targetClass, Secured.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.junit.jupiter.api.Test;

import org.springframework.core.annotation.AnnotationConfigurationException;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.intercept.method.MockMethodInvocation;
import org.springframework.security.authentication.TestAuthentication;
import org.springframework.security.authentication.TestingAuthenticationToken;
Expand Down Expand Up @@ -225,6 +226,48 @@ public void checkInheritedAnnotationsWhenConflictingThenAnnotationConfigurationE
.isThrownBy(() -> manager.check(authentication, methodInvocation));
}

@Test
public void checkRequiresUserWhenMethodsFromInheritThenApplies() throws Exception {
MockMethodInvocation methodInvocation = new MockMethodInvocation(new RolesAllowedClass(),
RolesAllowedClass.class, "securedUser");
Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager();
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation);
assertThat(decision.isGranted()).isTrue();
}

@Test
public void checkPermitAllWhenMethodsFromInheritThenApplies() throws Exception {
MockMethodInvocation methodInvocation = new MockMethodInvocation(new PermitAllClass(), PermitAllClass.class,
"securedUser");
Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager();
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation);
assertThat(decision.isGranted()).isTrue();
}

@Test
public void checkDenyAllWhenMethodsFromInheritThenApplies() throws Exception {
MockMethodInvocation methodInvocation = new MockMethodInvocation(new DenyAllClass(), DenyAllClass.class,
"securedUser");
Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager();
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation);
assertThat(decision.isGranted()).isFalse();
}

@RolesAllowed("USER")
public static class RolesAllowedClass extends SecuredAuthorizationManagerTests.ParentClass {

}

@PermitAll
public static class PermitAllClass extends SecuredAuthorizationManagerTests.ParentClass {

}

@DenyAll
public static class DenyAllClass extends SecuredAuthorizationManagerTests.ParentClass {

}

public static class TestClass implements InterfaceAnnotationsOne, InterfaceAnnotationsTwo {

public void doSomething() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.intercept.method.MockMethodInvocation;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.TestAuthentication;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authorization.AuthorizationDecision;
Expand Down Expand Up @@ -167,6 +168,21 @@ public void checkInheritedAnnotationsWhenConflictingThenAnnotationConfigurationE
.isThrownBy(() -> manager.check(authentication, result));
}

@Test
public void checkRequiresUserWhenMethodsFromInheritThenApplies() throws Exception {
MockMethodInvocation methodInvocation = new MockMethodInvocation(new PostAuthorizeClass(),
PostAuthorizeClass.class, "securedUser");
MethodInvocationResult result = new MethodInvocationResult(methodInvocation, null);
PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager();
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, result);
assertThat(decision.isGranted()).isTrue();
}

@PostAuthorize("hasRole('USER')")
public static class PostAuthorizeClass extends SecuredAuthorizationManagerTests.ParentClass {

}

public static class TestClass implements InterfaceAnnotationsOne, InterfaceAnnotationsTwo {

public void doSomething() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.AfterEach;
Expand All @@ -30,6 +32,7 @@
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.intercept.method.MockMethodInvocation;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.authentication.TestAuthentication;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
Expand Down Expand Up @@ -170,6 +173,34 @@ public Object proceed() {
SecurityContextHolder.setContextHolderStrategy(saved);
}

@Test
public void checkPostFilterWhenMethodsFromInheritThenApplies() throws Throwable {
String[] array = { "john", "bob" };
MockMethodInvocation methodInvocation = new MockMethodInvocation(new PostFilterClass(), PostFilterClass.class,
"inheritMethod", new Class[] { String[].class }, new Object[] { array }) {
@Override
public Object proceed() {
return array;
}
};
PostFilterAuthorizationMethodInterceptor advice = new PostFilterAuthorizationMethodInterceptor();
Object result = advice.invoke(methodInvocation);
assertThat(result).asInstanceOf(InstanceOfAssertFactories.array(String[].class)).containsOnly("john");
}

@PostFilter("filterObject == 'john'")
public static class PostFilterClass extends ParentClass {

}

public static class ParentClass {

public String[] inheritMethod(String[] array) {
return array;
}

}

@PostFilter("filterObject == 'john'")
public static class TestClass implements InterfaceAnnotationsOne, InterfaceAnnotationsTwo {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.lang.annotation.RetentionPolicy;
import java.util.function.Supplier;

import jakarta.annotation.security.DenyAll;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import org.junit.jupiter.api.Test;

import org.springframework.aop.TargetClassAware;
Expand Down Expand Up @@ -147,6 +150,20 @@ public void checkTargetClassAwareWhenInterfaceLevelAnnotationsThenApplies() thro
assertThat(decision.isGranted()).isTrue();
}

@Test
public void checkRequiresUserWhenMethodsFromInheritThenApplies() throws Exception {
MockMethodInvocation methodInvocation = new MockMethodInvocation(new PreAuthorizeClass(),
PreAuthorizeClass.class, "securedUser");
PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager();
AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation);
assertThat(decision.isGranted()).isTrue();
}

@PreAuthorize("hasRole('USER')")
public static class PreAuthorizeClass extends SecuredAuthorizationManagerTests.ParentClass {

}

public static class TestClass implements InterfaceAnnotationsOne, InterfaceAnnotationsTwo {

public void doSomething() {
Expand Down
Loading

0 comments on commit f0516e0

Please sign in to comment.