将Spring Boot请求URL和响应代码记录到数据库

时间:2018-02-07 10:36:30

标签: java spring spring-boot

我正在努力将以下详细信息“username,authentication_status,remote_ip,request_url,response_code”记录到Oracle数据库,以获取针对成功和不成功请求的Spring Boot应用程序的每个GET请求。

我目前正在使用以下类记录用户名,身份验证状态并请求IP地址,但我无法获取请求的网址和响应代码。不太熟悉Spring Boot,但是我可以轻松获得这些细节吗?

@Component
public class AuditLogger {

    @Autowired
    JdbcTemplate jdbcTemplate;

    @EventListener
    public void auditEventHappened(AuditApplicationEvent auditApplicationEvent) {

        AuditEvent auditEvent = auditApplicationEvent.getAuditEvent();
        WebAuthenticationDetails details = (WebAuthenticationDetails) auditEvent.getData().get("details");

        // Log this to the database
        String sqlStatement = "INSERT INTO API_AUDIT(USERNAME,AUTHENTICATION_STATUS,REMOTE_IP,REQUEST_URL,RESPONSE_CODE) VALUES (" 
                            + "'" + auditEvent.getPrincipal() + "', "
                            + "'" + auditEvent.getType() + "', "
                            + "'" + details.getRemoteAddress() + "',"
                            + "null," // This should be the request url
                            + "null"  // This should be the response code
                            + ")";

        jdbcTemplate.execute(sqlStatement);
    }
}

1 个答案:

答案 0 :(得分:0)

也许不是最优雅或最有效的解决方案,但似乎可以满足我的要求。每个请求都会触发auditEventHappened,该请求将插入请求信息并拉回Oracle rowId,然后将其用于doFilterInternal方法中,以更新数据库记录上的响应代码。随时发表评论。

// Hold the ID of the inserted audit record.
private Integer rowId; 

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);

    filterChain.doFilter(wrappedRequest, response);
    Integer status = response.getStatus();

    String query = "UPDATE AUDIT_LOG SET RESPONSE = :responseCode where id = :rowId";
    SqlParameterSource parameters = new MapSqlParameterSource()
        .addValue("responseCode", status)
        .addValue("rowId", rowId);

    namedParameterJdbcTemplate.update(query, parameters);
}


@EventListener
public void auditEventHappened(AuditApplicationEvent auditApplicationEvent) {

    AuditEvent auditEvent = auditApplicationEvent.getAuditEvent();

    ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
    HttpServletRequest req = sra.getRequest();

    String query = "INSERT INTO AUDIT_LOG (USERNAME,AUTH_STATUS,REQUEST_IP,SERVER_IP,REQUEST_URL,RESPONSE_CODE) VALUES (:1,:2,:3,:4,:5,:6)";
    KeyHolder holder = new GeneratedKeyHolder(); // Required to get the inserted record ID from the database. 

    SqlParameterSource parameters = new MapSqlParameterSource()
            .addValue("1", auditEvent.getPrincipal())
            .addValue("2", auditEvent.getType())
            .addValue("3", req.getRemoteAddr())
            .addValue("4", req.getLocalAddr())
            .addValue("5", req.getRequestURI())
            .addValue("6", null);      

    // Issue the statement to the database. Pull back the ID column of inserted record. Store in keyholder.
    namedParameterJdbcTemplate.update(query, parameters, holder, new String[]{"ID"});
    rowId = holder.getKey().intValue(); // Get the inserted ID from the keyholder, set globally for doFilterInternal which is about to trigger. 

}