Spring Data,Spring Security和Envers集成

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

软件架构

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

典型的流程由我的Spring MVC Controller处理,并传递到注入的服务,该服务管理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不允许这样做(还可以吗?)。 因此,基本上有三个选项(假设您关心检索:此类信息可能不为用户所见,并且您可以始终连接到数据库以在-if-需要访问数据时进行查询):

  • 创建代码以检索数据。 显然,您不能使用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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值