Ale*_*min 5 spring spring-security spring-el
我开始需要发明一种新型的注释,其中一个字段是 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
Run Code Online (Sandbox Code Playgroud)
但问题是:最适合我的情况的 MethodSecurityExpressionRoot 是包本地的。甚至有一项在 Spring Security JIRA 中公开的任务,一年来没有得到开发人员的任何关注。
而且,即使它不是包的地方,我还有哪里获得方法的对象弱的理解setTrustResolver
,setRoleHierarchy
和setPermissionEvaluator
的SecurityExpressionRoot
类,它似乎有需要为它的正常运作。
所以,我的问题是:如何正确获取正确的SecurityExpressionRoot
-subclass 实例以及如何使用所需的对象填充它?
我正在解决同样的问题。我有一个菜单项列表。每个菜单项都包含一个安全表达式字符串 (SpEl)。我尝试使用 @PostFilter("filterObject.securityExpression") 但我不知道如何评估 SpEl 字符串内的 SpEl 字符串。
所以我最终得到了自定义评估器 bean。深受 org.thymeleaf.extras.springsecurity4.auth.AuthUtils 的启发
评估器使用与 Web 安全过滤器相同的 SecurityExpressionHandler。这意味着有必要为评估上下文提供请求和响应。但这应该不会很复杂,因为 Spring 将这些值注入到控制器方法中。
评估人:
@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()));
}
}
Run Code Online (Sandbox Code Playgroud)
作为控制器方法的用法:
@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());
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3042 次 |
最近记录: |