【问题标题】:Is it possible to implement method-level access checks with annotations?是否可以使用注释实现方法级访问检查?
【发布时间】:2011-10-01 09:21:54
【问题描述】:

考虑一些带有Users 和Groups 的基本授权框架,其中对方法的访问应通过检查来保护,以确保用户或组拥有必要的PriviledgeLevel 来执行该方法,否则会失败。

我想象的是这样的:

@AccessCheck(PriviledgeLevel.ADMINISTRATOR)
public static void secureMethod(){ ... }

代码检查的基本作用

if(currentUser.getPriviledgeLevel >= PriviledgeLevel.ADMINISTRATOR ||
   currentUser.getGroup.priviledgeLevel >= PriviledgeLevel.ADMINISTRATOR)
  // Allow access
else
  // Deny access       

这样可以实现吗?

我做了一些研究,指出了一些基于 AspectJ 的现有事物,主要是 Security Annotation Framework (SAF) 和 Spring Security

我有点担心,因为 SAF 似乎不再活跃,而且文档也不是那么好。

我不确定 Spring Security,但它似乎更专注于 Web 相关主题中的安全问题。

Java Authentication and Authorization Service 好像是相关的,但是没有使用注解的方式。

尝试使用这种声明性方法定义这些安全要求是否有意义?

是否还有我缺少的另一个库/框架,它已经实现了我想要的或者一些在这里相关的技术?

或者有一个完全不同的解决方案(比如实现我自己的ClassLoader,...),它比我想象的更好(就图书馆用户的简洁性和可读性而言)?

【问题讨论】:

  • Spring Security 是一个自上而下的解决方案,它不仅专注于与 Web 相关的安全性。实际上,我开始在我的业务层中使用 Spring Security,然后在 Web 安全中使用它。

标签: java security spring annotations spring-security


【解决方案1】:

在 Spring Security 中,the docs 状态下,@Secured@PreAuthorize 都可以在方法级别使用。

要启用@PreAuthorize(如果您还没有...),您需要输入<global-method-security pre-post-annotations="enabled" /> 在您的配置 XML 中;

对于@Secured,请使用<global-method-security secured-annotations="enabled" />

更多详情,请参考this article

【讨论】:

    【解决方案2】:

    使用Spring Security,您只需添加:

    @Secured("ADMINISTRATOR")
    public static void secureMethod(){ ... }
    

    并通过以下方式正确配置:

    1. 使用JdbcDaoImpl 作为您的UserDetailsService
    2. enable group support
    3. 自定义查询(如果您使用数据库凭据存储)

    如果您不使用数据库凭据存储,只需配置您的首选UserDetailsService 以将用户和组凭据添加到生成的UserDetails 的权限。

    当然,如果不检查 documentation 中的概念,很难理解它,但是使用 spring security 完全可以进行方法级别的访问检查,这是我最喜欢的技术。

    【讨论】:

    • 是的,Spring Security 让这项工作变得轻松,而且它真的非常灵活,您几乎可以在任何地方配置行为,是的(默认情况下)适用于 Web 应用程序,但您可以保护方法调用,由模式和 jsp 片段组成的 url。当然,您可以扩展它以按照自己的方式实现安全性
    【解决方案3】:

    我认为 AspectJ 会做你想做的事。我们有一大堆方法,您需要某些访问权限,我们创建了一个 AspectJ 方面,如果用户没有这些权限,它将检查并出错。

    另外,由于 AspectJ 在编译时被“编织”到类中,因此无法通过配置禁用它。

    我们也使用 Spring Security,可以同时使用两者!

    【讨论】:

      【解决方案4】:

      您可以通过使用动态代理自己轻松完成这项工作。

      public interface MyInterface {
                 @AccessCheck(Privilege.ADMIN)
                 public void doSomething();
      }
      

      代理将在实现您的接口的类上创建,您将使用自定义注释来注释您的接口。

       MyInterface aInterface = (MyInterface) java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
                      .getClassLoader(), obj.getClass().getInterfaces(),
                      new YourProxy(new Implementation());
      

      在你的代理的invoke()方法中,你可以检查你的方法是否有注解,如果不满足权限则抛出SecurityException。

      public YourProxy implements InvocationHandler {
               ....
               public Object invoke(Object proxy, Method method, Object[] args)
              throws Throwable {
      
                    if ( method.isAnnotationPresent(AccessCheck.class) {
                          ....// do access check here and throw SecurityException()
               }
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多