Browse Source

SpEL Propagates Authorization Exceptions

Closes gh-16697
pull/16724/head
Josh Cummings 11 months ago
parent
commit
46cd94b5f4
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
  1. 16
      core/src/main/java/org/springframework/security/authorization/method/ExpressionUtils.java
  2. 15
      core/src/test/java/org/springframework/security/authorization/method/ExpressionUtilsTests.java

16
core/src/main/java/org/springframework/security/authorization/method/ExpressionUtils.java

@ -19,6 +19,7 @@ package org.springframework.security.authorization.method; @@ -19,6 +19,7 @@ package org.springframework.security.authorization.method;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.authorization.ExpressionAuthorizationDecision;
@ -43,9 +44,24 @@ final class ExpressionUtils { @@ -43,9 +44,24 @@ final class ExpressionUtils {
"SpEL expression must return either a Boolean or an AuthorizationDecision");
}
catch (EvaluationException ex) {
AuthorizationDeniedException denied = findAuthorizationException(ex);
if (denied != null) {
throw denied;
}
throw new IllegalArgumentException("Failed to evaluate expression '" + expr.getExpressionString() + "'",
ex);
}
}
static AuthorizationDeniedException findAuthorizationException(EvaluationException ex) {
Throwable cause = ex.getCause();
while (cause != null) {
if (cause instanceof AuthorizationDeniedException denied) {
return denied;
}
cause = cause.getCause();
}
return null;
}
}

15
core/src/test/java/org/springframework/security/authorization/method/ExpressionUtilsTests.java

@ -22,9 +22,11 @@ import org.springframework.expression.Expression; @@ -22,9 +22,11 @@ import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.authorization.ExpressionAuthorizationDecision;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class ExpressionUtilsTests {
@ -48,10 +50,23 @@ public class ExpressionUtilsTests { @@ -48,10 +50,23 @@ public class ExpressionUtilsTests {
assertThat(ExpressionUtils.evaluate(expression, context)).isInstanceOf(ExpressionAuthorizationDecision.class);
}
@Test
public void evaluateWhenExpressionThrowsAuthorizationDeniedExceptionThenPropagates() {
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("#root.throwException()");
StandardEvaluationContext context = new StandardEvaluationContext(this);
assertThatExceptionOfType(AuthorizationDeniedException.class)
.isThrownBy(() -> ExpressionUtils.evaluate(expression, context));
}
public AuthorizationDecision returnDecision() {
return new AuthorizationDecisionDetails(false, this.details);
}
public Object throwException() {
throw new AuthorizationDeniedException("denied");
}
public boolean returnResult() {
return false;
}

Loading…
Cancel
Save