当前位置: 首页 > 工具软件 > Envers > 使用案例 >

envers_Spring Data,Spring Security和Envers集成

谢裕
2023-12-01

envers

Spring Data JPA,Spring Security和Envers是我个人喜欢使用的库(我倾向于认为它们在各自的类别中被认为是同类中最好的)。 无论如何,我想实现一个我认为简单的用例:实体必须经过Envers审核,但是修订必须包含发起该操作的用户的身份。 尽管看起来很简单,但要实现这一目标我仍然要克服一些挑战。 本文列出了它们,并提供了可能的解决方案。

软件架构

我使用Spring MVC作为Web框架,配置为使用Spring Security。 为了简化我的开发,Spring Security配置了可识别的登录名/密码。 可以轻松地将其连接到更合适的后端。 本着同样的精神,我在H2内存数据库上的驱动程序管理器连接周围使用了数据源包装器。 只需通过Spring配置更改即可。

典型的流程由我的Spring MVC控制器处理,并传递到注入的服务,该服务管理Spring Data JPA存储库(访问数据库的组件)。

事实

在开发过程中,以下事实已被证明是一个障碍(阅读要克服的障碍):

  • Spring Security 3.1.1.RELEASE(最新)使用Spring 3.0.7.RELEASE(不是最新的)
  • Spring Data JPA使用(等待它)JPA2。因此,您必须使用LocalContainerEntityManagerFactoryBean参数化Spring配置,然后使用要使用的实现来配置EntityManager工厂bean(在本例中为Hibernate)。 一些传递的参数可跨不同的JPA实现移植,而其他地址则专门针对Envers,因此是完全不可移植的。
<beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">
    <propertyname="jpaDialect">
        <beanclass="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    </property>
</bean>
<beanclass="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <propertyname="dataSource"ref="dataSource"/>
    <propertyname="jpaVendorAdapter">
        <beanclass="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <propertyname="generateDdl"value="true"/>
            <propertyname="database"value="H2"/>
            <propertyname="showSql"value="true"/>
        </bean>
    </property>
    <propertyname="jpaProperties">
        <props>
            <propkey="org.hibernate.envers.auditTablePrefix"></prop>
            <propkey="org.hibernate.envers.auditTableSuffix"> _HISTORY </prop>
        </props>
    </property>
</bean>
  • Spring Data JPA确实以Auditable接口的形式提供了一些审计功能。 Auditables有createdBycreatedDatemodifiedBymodifiedDate性能。 不幸的是,该库没有存储实体的先前状态:我们必须使用提供此功能的Envers
  • 疯狂地战斗之后,我意识到将Envers集成到Spring Data JPA中并不是一件容易的事,并且偶然发现了Spring Data Envers模块,它确实完成了这项工作。 我没有在任何存储库中找到可用的Maven工件,因此我克隆了Git存储库并构建了当前版本(然后是0.1.0.BUILD-SNAPSHOT)。 它为我提供了对该项目做出非常微薄贡献的机会。

从好的方面来说,尽管我搜索了所有示例,但最新版本的Hibernate不仅随Envers一起提供,而且由于使用了智能服务提供商 ,因此不需要注册Envers侦听器的任何配置。 您只需要在类路径上提供JAR,JAR本身就负责注册。 这使Envers集成更加简单。

如何

除了添加Spring Data Envers,几乎没有想象力,因为它是Envers的基本用法。

  • 创建具有所需属性(用户)的修订实体:
    @RevisionEntity(AuditingRevisionListener.class)
    @Entity
    publicclassAuditedRevisionEntityextendsDefaultRevisionEntity{
    
        privatestaticfinallongserialVersionUID=1L;
        privateStringuser;
    
        publicStringgetUser(){
            returnuser;
        }
    
        publicvoidsetUser(Stringuser){
            this.user=user;
        }
    }
  • 创建侦听器以从Spring Security上下文获取身份,并在修订实体上进行设置:
    publicclassAuditingRevisionListenerimplementsRevisionListener{
        @Override
        publicvoidnewRevision(ObjectrevisionEntity){
            AuditedRevisionEntityauditedRevisionEntity=(AuditedRevisionEntity)revisionEntity;
            StringuserName=SecurityContextHolder.getContext().getAuthentication().getName();
            auditedRevisionEntity.setUser(userName);
        }
    }

Presto,您完成了...

坏消息

……不是吗? 当写入数据库时​​,上述解决方案可以完美地工作。 麻烦之处在于尝试从那里获取信息,因为Spring Data API不允许这样做(还可以吗?)。 因此,基本上有三个选项(假设您关心检索:用户可能看不到这种信息,并且在需要访问数据时始终可以连接到数据库以进行查询):

  • 创建代码以检索数据。 显然,您不能使用Spring Data JPA(您的实体缺少`user`字段,它是在运行时“创建”的)。 恕我直言,最好的方法是创建一个侦听器,该侦听器在已审核实体的读取查询中获取数据并返回增强型实体。 性能和设计方面的考虑因素都不支持这一点。
  • 通过使用使其依赖于Spring Data内部的反射来修改API。 与以前一样,这是一个糟糕的选择,但出于教育目的,我这样做是:
    Revisionsrevisions=stuffRepository.findRevisions(stuff.getId());
    
    ListauditedRevisionEntities=newArrayList();
    
    for(Revisionrevision:revisions.getContent()){
        Fieldfield=ReflectionUtils.findField(Revision.class,"metadata");
    
        // Oh, it's ugly!
        ReflectionUtils.makeAccessible(field);
        @SuppressWarnings("rawtypes")
        RevisionMetadatametadata=(RevisionMetadata)ReflectionUtils.getField(field,revision);
        AuditedRevisionEntityauditedRevisionEntity=(AuditedRevisionEntity)metadata.getDelegate();
    
        // Do what your want with auditedRevisionEntity...
    }
  • 最后但并非最不重要的一点是,您可以为Spring Data的代码做出贡献。 当然,您需要了解API以及内部知识,技能和时间,但这是值得的worth

结论

集成异构库几乎不是一个过渡。 对于Spring Data JPA和Envers,由于使用了Spring Data Envers库,因此就像馅饼一样容易。 但是,如果需要使审核数据可访问,则需要进一步集成。

这篇文章的来源是在这里 ,在Eclipse / Maven的格式。

翻译自: https://blog.frankel.ch/spring-data-spring-security-and-envers-integration/

envers

 类似资料: