Java 如何使用Envers审计Hibernate读取?

Java 如何使用Envers审计Hibernate读取?,java,hibernate,hibernate-envers,Java,Hibernate,Hibernate Envers,我一直在从事应用程序审计工作,并已成功连接Hibernate Envers 4.3.11以捕获创建、更新和删除,但我找不到任何有关实体审计读取的文档 这在Envers中是可能的,还是最好依赖log4j或类似的工具?我认为这是不可能的。我们有类似的用例,我们使用拦截器在我们的服务上生成审计记录。是的,使用Hibernate Envers可以审计实体的读取。 下面是一个从第一次修订的审核表中读取记录的示例 /*Audit Reader*/ public AuditReader getAuditRe

我一直在从事应用程序审计工作,并已成功连接Hibernate Envers 4.3.11以捕获创建、更新和删除,但我找不到任何有关实体审计读取的文档


这在Envers中是可能的,还是最好依赖log4j或类似的工具?

我认为这是不可能的。我们有类似的用例,我们使用拦截器在我们的服务上生成审计记录。

是的,使用Hibernate Envers可以审计实体的读取。 下面是一个从第一次修订的审核表中读取记录的示例

/*Audit Reader*/

public AuditReader getAuditReader() {
        return  AuditReaderFactory.get(getCrntSession());
    }

/*The method to read a record from an entity*/

Integer revisionNumber = (Integer) getAuditReader().createQuery()
                .forRevisionsOfEntity(Employee.class, false, true)
                .addProjection(AuditEntity.revisionNumber().min())
                .getSingleResult();

        AuditReader reader = getAuditReader();
        Employee emp=reader.findRevision(Employee.class, (Number)revisionNumber);

/* and if Employee has an createdDate record , we can read it using below*/:
       System.out.println(emp.getCreatedDate());

下面是对日志读取所做的操作。一段时间过去了,所以我可能错过了一个细节,但我认为这就是一切

下面是一个Envers
RevisionListener
实现。它获取IP地址和经过身份验证的用户名,并在每次读取时创建一个写入数据库的实体

package com.example.audit;

import javax.servlet.http.HttpServletRequest;

import org.hibernate.envers.RevisionListener;
import com.example.utilities.RequestUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class UserRevisionListener implements RevisionListener {

    @Override
    public void newRevision(Object revisionEntity) {
        final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        Assert.notNull(auth, "Could not find an Authentication object for this user");
        Assert.notNull(auth.getPrincipal(), "Principal must not be null.");

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder
                .currentRequestAttributes();
        Assert.notNull(servletRequestAttributes, "Current request attributes was null, remote address not attainable");

        HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest();
        Assert.notNull(httpServletRequest, "Request was null, remote address not attainable");

        String remoteAddress = RequestUtils.getClientIpAddr(httpServletRequest);
        Assert.notNull(remoteAddress, "Remote address was null");

        String username = ((UserDetails) auth.getPrincipal()).getUsername();
        Assert.notNull(username, "Could not audit record due to missing username");

        UserRevisionEntity userRevisionEntity = (UserRevisionEntity) revisionEntity;
        userRevisionEntity.setUsername(username);
        userRevisionEntity.setIp(remoteAddress);
    }
}
下面是Hibernate实体:

package com.example.audit;

import java.util.Set;

import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;

import org.hibernate.envers.DefaultRevisionEntity;
import org.hibernate.envers.ModifiedEntityNames;
import org.hibernate.envers.RevisionEntity;

@Entity
@RevisionEntity(UserRevisionListener.class)
public class UserRevisionEntity extends DefaultRevisionEntity {

    private static final long serialVersionUID = -3922860601141228497L;

    private String username;

    private String ip;

    @ElementCollection
    @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
    @Column(name = "ENTITYNAME")
    @ModifiedEntityNames
    private Set<String> modifiedEntityNames;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

}
它需要以下属性:

spring.jpa.properties.org.hibernate.envers.audit_table_suffix=_audit
spring.jpa.properties.org.hibernate.envers.store_data_at_delete=true
spring.jpa.properties.org.hibernate.envers.audit_strategy=org.hibernate.envers.strategy.ValidityAuditStrategy
spring.jpa.properties.org.hibernate.envers.audit_strategy_validity_store_revend_timestamp=true
spring.jpa.properties.org.hibernate.envers.track_entities_changed_in_revision=true

这看起来像是在查找以前审核过的记录。我想在每次读取实体后在审计表中存储一条记录。我一直在研究,看来envers不会支持这项行动。可能需要拦截请求并直接登录到文件或数据库。你找到解决方案了吗,OP?@VinhVO,我找到了一点解决方案。我将发布一个关于已经完成的工作的答案——由于时间的流逝,我忘记了这个问题。你用什么来完成这项工作?我做了一些关于hibernate相关工具的研究,但没有结果。我最终使用触发器监视每个数据库表的更改。
spring.jpa.properties.org.hibernate.envers.audit_table_suffix=_audit
spring.jpa.properties.org.hibernate.envers.store_data_at_delete=true
spring.jpa.properties.org.hibernate.envers.audit_strategy=org.hibernate.envers.strategy.ValidityAuditStrategy
spring.jpa.properties.org.hibernate.envers.audit_strategy_validity_store_revend_timestamp=true
spring.jpa.properties.org.hibernate.envers.track_entities_changed_in_revision=true