【问题标题】:Check permission; always a request against database?检查权限;总是对数据库的请求?
【发布时间】:2019-12-25 07:39:10
【问题描述】:

我有一个关于 Apache Shiro 的问题。 我正在使用权限和角色概念。

我在左侧有一个菜单,其中包含许多指向我的其他页面的链接(创建员工、显示员工列表等)。 对于每个菜单项,我还可以安全地隐藏它(取决于权限),例如:

<pm:menu widgetVar="me"
rendered="#{checkPermissionController.checkPermission(['myprofile:show', 'myprofile:edit'])}">

为了检查用户是否被允许,我的 bean 中有这两个函数:

/**
     * Check permission for login User
     * 
     * @return
     * @throws IOException
     * @throws PermissionGroupNotFoundException
     */
    public boolean checkPermission(String permissionName) throws IOException {

        if (loginBean.getCurrentUserShiro().isPermitted(permissionName)) {
            return true;
        }

        return false;
    }

    /**
     * If one of the permission is true
     * 
     * @param strings
     * @return
     */
    public boolean checkPermission(List<String> list) {

        int i = list.size();

        if (i != 0) {
            for (String s : list) {
                if (loginBean.getCurrentUserShiro().isPermitted(s)) {
                    return true;
                }
            }
        }

        return false;
    }

我现在的问题更多是针对性能。 如果用户被允许或不允许,Apache Shiro 是否为每个菜单条目执行对数据库的请求? 还是 Shiro 在登录时获取用户的所有权限并将其“持有”在“Shiro 用户”对象中?

如果是:我该如何改进?

编辑: 这是我的 LoginBean:

@SessionScoped
@Named
public class LoginBean implements Serializable {

private Subject currentUserShiro;

public String submit() {

        LOGGER.info("START submit");

        try {

            currentUserShiro = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
....
}

    ////////////////////
    // Getter + Setter
    ////////////////////
    public String getUsername() {
        return username;
    }

    public Subject getCurrentUserShiro() {
        return currentUserShiro;
    }
            currentUserShiro.login(token);

【问题讨论】:

  • "Apache Shiro 是否为每个菜单项执行" - 这完全取决于getCurrentUserShiro() 的实现。 “如果是:我该如何改进它?” - 使用缓存。
  • @Selaron 是对的,这个编程问题也会出现在单元测试中......
  • 我已经更新了代码...我的 bean 是 @SessionScoped....你的意思是什么类型的缓存? p:来自primefaces的缓存?还是在 Shiro 中缓存?我应该使用哪个缓存提供程序?...
  • 或缓存在会话范围 bean 中的列表/映射中...但是是的,p:cache 也可能有帮助(如果您按用户缓存)并且关于 " Apache Shiro 是否为每个执行如果用户被允许,菜单项对数据库的请求?还是 Shiro 在登录时获取用户的所有权限并将其“保留”在“Shiro 用户”对象中?” 阅读 shiro 手册或设置一些断点或调试日志...

标签: performance jsf shiro


【解决方案1】:

我建议使用 Shiro 的过滤器来为您处理实际的登录逻辑。 https://shiro.apache.org/web.html

否则,您最终可能会得到与您的会话无关的主题。看起来您的应用程序可能会在任何时候强制登录 getCurrentUserShiro 被调用。您应该让框架为您处理。

它不是 JSF,但您可以在这里看到一个基本的 JSP 示例(Shrio 配置逻辑将是相同的): https://github.com/apache/shiro/tree/master/samples/servlet-plugin

您可能只需将登录页面:https://github.com/apache/shiro/blob/master/samples/servlet-plugin/src/main/webapp/login.jsp 替换为您的自定义页面

【讨论】:

  • 我不确定你的意思....我的项目中已经有 shiro.ini 了?我也有一个登录页面。否则用户没有登录....
  • 对,但您仍然直接管理身份验证部分,我建议您让 Shiro 处理,而不是手动调用 subject.login()
  • 我不确定你的意思。如何在不调用 subject.login 的情况下处理它?我需要 jsf 页面中的一个按钮,这也在调用 subject.login ?
  • 让你的应用无需任何认证授权自定义代码。现在添加 shiro.ini 并在 web.xml 中输入 Shiro 环境监听器。让 Shiro 为你做所有的验证码。
  • @MarcMeister,看看我指给你的示例代码。只需发布到同一个表单,您的用户就会登录。
猜你喜欢
  • 1970-01-01
  • 2017-09-26
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
  • 2021-08-22
  • 2016-10-04
  • 1970-01-01
  • 2016-06-02
相关资源
最近更新 更多