使用Wicket Auth-Role在Wicket组件上进行授权

4
我正在使用wicket 1.4.9,并且实现了spring + wicket auth-role,并在页面上使用@AuthorizeInstantiation基于角色。我有多个自定义角色。
我遵循了这个链接来实现基础功能: https://cwiki.apache.org/WICKET/spring-security-and-wicket-auth-roles.html 之后,我实现了自己的UserDetailsService,以从数据库中获取自己的角色/用户。
现在,如何对组件(例如链接、按钮)的角色进行控制?比如说,只有SUPER_USER、DR_MANAGER才能访问链接A。(角色来自数据库)
我已经这样做了,似乎可以工作,但这是好的方法吗?OrbitWebSession是AuthenticatedWebSession类型。
        @Override
        public boolean isVisible() {
            if(OrbitWebSession.get().getRoles().hasRole("SUPER_USER")){
                return true;
            }
            return false;
        }

谢谢。


1
你提到角色是基于数据库查询的。在isVisible()中执行昂贵的调用要小心。虽然这是一个简单的计算,但确保一切都被正确缓存。 - jbrookover
好的,请澄清我的困惑,如果我的自定义AunthenticatedWebSession覆盖了getRoles()方法,并且该方法从SecurityContextHolder获取角色,而SecurityContextHolder从我的UserDetails加载角色,那么它不是被缓存了吗?还是每次调用都会从我的用户实体中获取所有角色? - Shahriar
我不熟悉Spring;我只是想确保您的用户对象被缓存 - 每次运行此方法时运行数据库查询会很糟糕。 - jbrookover
3个回答

7

覆盖 isVisible 方法一直是一个很大的麻烦。相反,可以看一下 MetaDataRoleAuthorizationStrategy。你可以调用 authorize(Component component, Action action, String roles) 方法,并传入 Action RENDER 和想要允许的角色。这样,无论组件是什么,只要授权策略在您的 Web 应用程序中注册,它就会自动隐藏其他角色。基本上它做的事情与 Holms 的回答相同,除了你不必子类化任何东西。


3

你已经在正确的轨道上了,唯一需要改变的是:

@Override
public boolean isVisible() {
    return super.isVisible() && OrbitWebSession.get().getRoles().hasRole("SUPER_USER");
}

这样,您就不会意外覆盖其默认可见行为,例如如果父组件不可见。


这不是我在Wicket中会采用的方式,其他答案使用标准的Wicket授权实现,建议您查看它们。 - Manuel Manhart

3

使用@AuthorizeAction注释,您可以根据角色控制组件是否呈现。这很容易使用,但您必须子类化要授权的组件。

@AuthorizeAction(action = Action.RENDER, roles = { "SUPER_USER", "DR_MANAGER" })
class UserAdminPageLink extends BookmarkablePageLink<String> {
   //Implementation…
}
add(new UserAdminPageLink("UserAdminPageLink", UserAdminPage.class));

请查看Wicket Examples - Authorization获取一些可用的代码。


谢谢,我会看一下的。但是我的应用程序有很多组件需要这个控件。我担心我不得不创建太多的子类! - Shahriar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接