代码之家  ›  专栏  ›  技术社区  ›  Piotr

保护域对象的正确方法?

  •  1
  • Piotr  · 技术社区  · 13 年前

    如果我有一个实体实体和一个带有以下接口的服务EntityService和EntityServiceFacade:

    interface EntityService {
    
     Entity getEntity(Long id);
    
    }
    
    interface EntityServiceFacade {
    
     EntityDTO getEntity(Long id);
    
    }
    

    通过在服务级别控制对getEntity方法的访问,我可以轻松地保护对实体的读取访问。但是,一旦facade引用了一个实体,我如何控制对它的写访问呢?如果我有一个saveEntity方法,并在服务(而不是facade)级别上控制访问(这里有Spring安全注释):

    class EntityServiceImpl implements EntityService {
    
     ...
    
     @PreAuthorize("hasPermission(#entity, 'write')")
     public void saveEntity(Entity entity) {
    
      repository.store(entity);
     }
    
    }
    
    class EntityServiceFacadeImpl implements EntityServiceFacade {
    
     ...
    
     @Transactional
     public void saveEntity(EntityDTO dto) {
    
      Entity entity = service.getEntity(dto.id);
      entity.setName(dto.name);
      service.save(entity);
     }
    
    }
    

    这里的问题是,访问控制检查在我更改了实体的名称之后就已经发生了,所以这还不够。

    你们是怎么做到的?您是否改为保护域对象方法?

    谢谢

    编辑:

    如果您保护域对象,例如使用以下批注:

    @PreAuthorize("hasPermission(this, 'write')")
    public void setName(String name) { this.name = name; }
    

    那么我是否打破了域模型(根据DDD?)

    编辑2

    我找到一个 thesis 关于这个问题。论文的结论是,一种很好的方法是对域对象方法进行注释以保证它们的安全。有什么想法吗?

    2 回复  |  直到 13 年前
        1
  •  1
  •   Mike Samuel    13 年前

    如果 Entity 是一个界面,你就不能把它膜化吗?

    所以如果实体是这样的:

    interface Entity {
      int getFoo();
      void setFoo(int newFoo);
    }
    

    创造一个膜状

    final class ReadOnlyEntity implements Entity {
      private final Entity underlying;
    
      ReadOnlyEntity(Entity underlying) { this.underlying = underlying; }
    
      public int getFoo() { return underlying.getFoo(); }  // Read methods work
    
      // But deny mutators.
      public void setFoo(int newFoo) { throw new UnsupportedOperationException(); }
    }
    

    如果注释了read方法,则可以使用代理类自动创建跨多个类的膜(以便readonly上的get方法 实体 返回一个 EntityPart 返回只读 实体艺术 ).

    见深度衰减 http://en.wikipedia.org/wiki/Object-capability_model 有关此方法的详细信息。

        2
  •  2
  •   Johannes Rudolph    13 年前

    我不担心单个实体方法或属性被修改的安全性。

    如果可以控制持久性,则不一定总是需要阻止用户更改内存中的实体。

    这里最大的问题是UX,您希望尽早通知用户,她可能无法持久化对该实体所做的更改。您需要做的决定是,是否可以将安全检查延迟到持久化时间,或者是否需要在之前通知用户(例如,通过停用UI元素)。