gpt4 book ai didi

spring - 如何评估自定义 java 代码中的 SpEL 安全表达式?

转载 作者:行者123 更新时间:2023-12-02 07:14:12 25 4
gpt4 key购买 nike

我需要发明一种新型注释,其中一个字段是 Spring 表达式语言(又名 SpEL)表达式字符串。

经过一番谷歌搜索和检查现有的类后,我发现评估表达式的方式可能是这样的(如果我有任何错误,请纠正我):

    ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("isAnonymous()"); // well, this is only an example
SecurityExpressionRoot context = ... obtaining the instance of subclass of SecurityExpressionRoot ...
System.out.println(exp.getValue(context)); // just an example

但问题是:最适合我的情况 MethodSecurityExpressionRoot 是 package-local。甚至还有一个task about making it public in Spring Security JIRA一年来没有引起开发人员的任何关注。

即使它不是包本地的,我仍然对从哪里获取方法对象的理解很薄弱setTrustResolver , setRoleHierarchysetPermissionEvaluatorSecurityExpressionRoot类,这似乎是其正常运行所必需的。

所以,我的问题是:如何正确获得正确的SecurityExpressionRoot -子类实例以及如何用所需的对象填充它?

最佳答案

我正在解决同样的问题。我有一个菜单项列表。每个菜单项都包含一个安全表达式字符串 (SpEl)。我尝试使用 @PostFilter("filterObject.securityExpression") 但我不知道如何计算 SpEl 字符串内的 SpEl 字符串。

所以我最终得到了自定义评估器 bean。深受 org.thymeleaf.extras.springsecurity4.auth.AuthUtils 的启发

评估器使用与 Web 安全过滤器相同的 SecurityExpressionHandler。这意味着有必要为评估上下文提供请求和响应。但这应该不会很复杂,因为 Spring 将这些值注入(inject)到 Controller 方法中。

评估者:

@Component
public class WebSecurityExpressionEvaluator {

private static final FilterChain EMPTY_CHAIN = (request, response) -> {
throw new UnsupportedOperationException();
};

private final List<SecurityExpressionHandler> securityExpressionHandlers;

public WebSecurityExpressionEvaluator(List<SecurityExpressionHandler> securityExpressionHandlers) {
this.securityExpressionHandlers = securityExpressionHandlers;
}

public boolean evaluate(String securityExpression, HttpServletRequest request, HttpServletResponse response) {
SecurityExpressionHandler handler = getFilterSecurityHandler();

Expression expression = handler.getExpressionParser().parseExpression(securityExpression);

EvaluationContext evaluationContext = createEvaluationContext(handler, request, response);

return ExpressionUtils.evaluateAsBoolean(expression, evaluationContext);
}

@SuppressWarnings("unchecked")
private EvaluationContext createEvaluationContext(SecurityExpressionHandler handler, HttpServletRequest request, HttpServletResponse response) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
FilterInvocation filterInvocation = new FilterInvocation(request, response, EMPTY_CHAIN);

return handler.createEvaluationContext(authentication, filterInvocation);
}

private SecurityExpressionHandler getFilterSecurityHandler() {
return securityExpressionHandlers.stream()
.filter(handler -> FilterInvocation.class.equals(GenericTypeResolver.resolveTypeArgument(handler.getClass(), SecurityExpressionHandler.class)))
.findAny()
.orElseThrow(() -> new IllegalStateException("No filter invocation security expression handler has been found! Handlers: " + securityExpressionHandlers.size()));
}
}

用作 Controller 方法:

@ModelAttribute("adminMenuItems")
public List<AdminMenuItem> getMenuItems(HttpServletRequest request, HttpServletResponse response) {
List<AdminMenuItem> menuItems = ...
return menuItems.stream().filter(item -> evaluator.evaluate(item.getSecurityExpression(), request, response)).collect(toList());
}

关于spring - 如何评估自定义 java 代码中的 SpEL 安全表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17263506/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com