我正在解決同樣的問題。我有一個菜單項列表。每個菜單項都包含一個安全表達式字符串(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()));
}
}
用法作爲控制器的方法:
@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());
}
你爲什麼不使用'DefaultMethodSecurityExpressionHandler'?如果我可能會問,你的用例有什麼特別之處,你需要一個新的註釋? –
感謝您指向'DefaultMethodSecurityExpressionHandler'的方向,但是您是否可以展示它應該用於的方式?什麼是'MethodInvocation'的東西,在那裏傳遞?你如何使用它? ---我的特殊用例是帶註釋控制器的建築物導航菜單;在某些情況下,我希望隱藏一些基於SpEL安全表達式的菜單項(例如,如果用戶未通過身份驗證或沒有「PROFILE」角色等,則不顯示「我的配置文件」菜單項); –
可能的重複http://stackoverflow.com/questions/6632982/how-to-create-custom-methods-for-use-in-spring-security-expression-language-anno – Ralph