Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用spring security和/或shiro的授权最佳实践_Java_Spring Security_Shiro - Fatal编程技术网

Java 使用spring security和/或shiro的授权最佳实践

Java 使用spring security和/或shiro的授权最佳实践,java,spring-security,shiro,Java,Spring Security,Shiro,我对使用Spring Security或Shiro处理“权利”概念的最佳方式的意见很感兴趣 例如,假设一个JAX-RS端点具有如下签名: AccountDetails getAccountDetails(String accountId); 使用Spring Security,我可能会对一个实现进行如下注释: @Secured(AUTHORIZED_USER) public AccountDetails getAccountDetails(String accountId) { ... }

我对使用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安全性并不完全简单,但我很想弄错)

或者,我可以想象引入一个
AccountId
域对象,以及一个工厂,如果当前安全上下文所持的原则允许用户查看该帐户,那么它只能成功地将
字符串
转换为
AccountId
。但这开始变得有点混乱

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


谢谢您的建议。

听起来您要做的是为特定帐户实现行级安全。还有其他Stackoverflow问题(和)讨论了这个问题的潜在解决方案。此外,第一个答案中提供的链接讨论了实现。但是,排名较高的答案建议直接在数据库级别实现行级安全性

与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);
    }
}
public boolean是允许的(SubjectPrincipals,Permission p){
if(CustomPermission的p实例){
CustomPermission cp=(CustomPermission)p;
Class type=cp.getType();//AccountDetails
整数id=cp.getId();//accountId
整数userId=principal.getPrimaryPrincipal();//或用户名
customPermissionCheckingLogic(用户id、类型、id);
}
}
显然,此实现依赖于CDI,您可以根据提供的对象类型确定要检查的表(JPA注释在这方面起作用)。此外,可能有一些方法可以连接到Shiro的注释扫描中,以提供比我在这里所做的更直接/本机权限功能