簡體   English   中英

如何使用Envers審核Hibernate讀取?

[英]How to audit Hibernate reads with Envers?

我一直在進行應用程序審核,並已成功連接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;
    }

}

這是RequestUtils.java

package com.example.utilities;

import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;

import org.springframework.util.Assert;

public final class RequestUtils {

    private static final String UNKNOWN = "unknown";

    private RequestUtils() {
    }

    /**
    * If any proxy or load balancer exists between the client and the server {@link HttpServletRequest#getRemoteAddr()}
    * will return localhost or the address of the middle machine.
    *
    * @param request
    *            a {@link HttpServletRequest}
    * @return The remote address of the client accessing the server.
    */
    public static String getClientIpAddr(HttpServletRequest request) {
        Assert.notNull(request, "Request must not be null");
        return Stream
                .of("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP",
                        "HTTP_X_FORWARDED_FOR")
                .filter(header -> validHeader(header, request))
                .map(header -> request.getHeader(header))
                .findFirst()
                .orElse(request.getRemoteAddr());
    }

    private static Boolean validHeader(String header, HttpServletRequest request) {
        String ip = request.getHeader(header);
        return !(ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM