【问题标题】:Best practices for entitlement using spring security and/or shiro使用 spring security 和/或 shiro 的最佳实践
【发布时间】:2011-08-26 12:49:56
【问题描述】:

我对使用 Spring Security 或 Shiro 处理“权利”概念的最佳方式的意见感兴趣。

例如,假设一个具有如下签名的 JAX-RS 端点:

AccountDetails getAccountDetails(String accountId);

使用 Spring Security,我可能会注释如下实现:

@Secured(AUTHORIZED_USER)
public AccountDetails getAccountDetails(String accountId) { ... }

或使用 Shiro,

@RequiresAuthentication
public AccountDetails getAccountDetails(String accountId) { ... }

然而,我正在寻找一些关于如何确保用户有权访问特定帐户 ID 的“最佳实践”的建议(我认为这称为“权利管理”)。

我可以想象几种不同的方法:

@Secured(AUTHORIZED_USER)
@AccountEntitled
public AccountDetails getAccountDetails(@Account String accountId) { ... }

(这让我觉得使用 Spring Security 并不完全简单,但我很想错)。

或者,我可以想象引入一个AccountId 域对象,以及一个工厂,它只有在当前安全上下文持有的原则允许用户看到该帐户的情况下才能成功地将String 转换为AccountId .但这开始有点混乱了。

总的来说,我不想在这里发明新概念;这似乎是面包和黄油的东西,但我没有太多运气在这里找到有关最佳实践的可靠建议。

感谢您的任何建议。

【问题讨论】:

    标签: java spring-security shiro


    【解决方案1】:

    听起来您正在尝试为特定帐户实施行级安全性。还有其他 Stackoverflow 问题(How to implement row-level security in Java?Database independent row level security solution)讨论了这个问题的潜在解决方案。此外,第一个答案中提供的链接讨论了实现Row Level Security with Spring and Hibernate。但是,排名较高的答案建议直接在数据库级别实施行级安全性。

    与 Shiro 合作过,我可以说是可以做到的。但是,您必须实现自己的安全结构(领域、权限、注释)以适应您描述的功能类型。一种方法是添加一个类似于您在上一个示例中的注释,指示该方法需要权限检查。此注解将绑定到一个拦截器,该拦截器反过来会生成适当的权限,然后调用安全框架来验证权限。

    它看起来像这样。

    方法:

    @RequiresAuthorization
    @Entitled
    public AccountDetails getAccountDetails(@Account String accountId) {...}
    

    拦截器:

    @Interceptor
    @Entitled
    public class EntitledInterceptor {
        @AroundInvoke
        public void interceptOrder(InvocationContext ctx) {
            // return type is AccountDetails 
            // parameter[0] is acccoundId
            Permission p = new CustomPermission(context.getMethod().getReturnType(),
                                                ctx.getParameters()[0]);
            if(SecurityUtils.getSubject().isPermitted(p)){
              return ctx.proceed();
            } else {
             throw new RowLevelSecurityException("No access!");
            }
    }
    

    领域:

    public boolean isPermitted(SubjectPrincipals principal, Permission p){
        if( p instanceof CustomPermission){
            CustomPermission cp = (CustomPermission) p;
            Class<?> type = cp.getType(); //AccountDetails
            Integer id = cp.getId(); //accountId
            Integer userId = principal.getPrimaryPrincipal(); //or username
            customPermissionCheckingLogic(userId, type, id);
        }
    }
    

    显然,此实现依赖于 CDI,并且您可以根据提供的对象类型确定要检查的表(JPA 注释在这方面起作用)。此外,可能有一些方法可以连接到 Shiro 的注释扫描,以提供比我在这里所做的更多的直接/本地权限功能。

    Documentation on CDI interceptors.

    【讨论】:

      猜你喜欢
      • 2010-11-07
      • 2018-04-24
      • 2013-04-29
      • 2016-04-08
      • 2013-10-02
      • 2011-03-20
      • 2015-03-18
      • 2015-09-11
      相关资源
      最近更新 更多