API安全(八)-审计

摘要:
审计日志一定要持久化,方便我们对问题的追溯,可以把它放到数据库中,也可以写到磁盘中。这里我们的审计功能选择Filter和Interceptor都可以,根据自己的喜好即可。

1、审计所在安全链路的位置,为什么

API安全(八)-审计第1张

如图所示,审计应该做在认证之后,授权之前。因为只有在认证之后,我们在记录日志的时候,在知道请求是那个用户发过来的;做在授权之前,哪些请求被拒绝了,在响应的时候,也可以把它记录下来。如果放到授权之后 ,那么被拒绝的请求就不能记录了。

审计日志一定要持久化,方便我们对问题的追溯,可以把它放到数据库中,也可以写到磁盘中。实际工作中,一般会发送到公司统一的日志服务上,由日志服务来存储。

2、审计采用的组件,及安全链路顺序的保障

首先,我们来明确一下各组件在请求中的执行顺序,如下图,依次是 Filter -> Interceptor -> ControllerAdvice -> AOP -> Controller

API安全(八)-审计第2张

对于Filter之间,我们可以使用@Order注解来确定执行顺序;对于Interceptor之间根据注册的先后顺序执行。这里我们的审计功能选择Filter和Interceptor都可以,根据自己的喜好即可。

3、实现审计功能

3.1、审计日志类及持久层接口

/*** 审计日志
 *
 * @authorcaofanqi
 * @date 2020/1/28 22:55
 */@Data
@Entity
@Table(name = "audit_log")
@EntityListeners(value = AuditingEntityListener.class)
public classAuditLogDO {

    @Id
    @GeneratedValue(strategy =GenerationType.IDENTITY)
    privateLong id;

    privateString httpMethod;

    privateString path;

    privateInteger httpStatus;

    @CreatedBy
    privateString username;

    @CreatedDate
    privateLocalDateTime requestTime;

    @LastModifiedDate
    privateLocalDateTime responseTime;

    privateString errorMessage;

}
/*** 审计日志Repository
 * @authorcaofanqi
 * @date 2020/1/28 23:13
 */
public interface AuditLogRepository extends JpaRepositoryImplementation<AuditLogDO,Long>{
}

3.2、开启JPA审计功能配置

/*** JPA相关配置
 *
 * @authorcaofanqi
 * @date 2020/1/29 1:13
 */@Configuration
@EnableJpaAuditing
public classJpaConfig {

    /*** 获取当前登陆用户
     */@Bean
    public AuditorAware<String>auditorAware() {
        return () ->{
            HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            UserDO user = (UserDO) request.getAttribute("user");
            if (user != null) {
                returnOptional.of(user.getUsername());
            } else{
                return Optional.of("anonymous");
            }
        };
    }

}

此处不懂的,可以去看我写的JPA文章:https://www.cnblogs.com/caofanqi/p/11996718.html

3.3、基于Filter实现审计功能AuditLogFilter,流控过滤器设置@Order(1)、认证过滤器设置@Order(2)

/*** 审计过滤器
 *
 * @authorcaofanqi
 * @date 2020/1/29 0:08
 */@Slf4j
@Order(3)
@Component
public class AuditLogFilter extendsOncePerRequestFilter {


    @Resource
    privateAuditLogRepository auditLogRepository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throwsServletException, IOException {

        log.info("++++++3、审计++++++");

        AuditLogDO auditLogDO = newAuditLogDO();
        auditLogDO.setHttpMethod(request.getMethod());
        auditLogDO.setPath(request.getRequestURI());
        //放入持久化上下文中,供异常处理使用
auditLogRepository.save(auditLogDO);
        request.setAttribute("auditLogId",auditLogDO.getId());

        //执行请求
filterChain.doFilter(request,response);

        //执行完成,从持久化上下文中获取,并记录响应信息
        auditLogDO =auditLogRepository.findById(auditLogDO.getId()).get();
        auditLogDO.setHttpStatus(response.getStatus());

        auditLogRepository.save(auditLogDO);

    }

}

3.4、异常处理ControllerAdvice

    /***
     * @parame 系统异常
     * @return系统异常及时间
     */@ExceptionHandler
    @ResponseStatus(code =HttpStatus.INTERNAL_SERVER_ERROR)
    public Map<String,Object>exceptionHandler(Exception e){
        /**  如果有异常的化,将审计日志取出,记录异常信息
         */HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Long auditLogId = (Long) request.getAttribute("auditLogId");
        AuditLogDO auditLogDO = auditLogRepository.findById(auditLogId).orElse(newAuditLogDO());
        auditLogDO.setErrorMessage(e.getMessage());
        auditLogRepository.save(auditLogDO);

        Map<String, Object> info =Maps.newHashMap();
        info.put("message", e.getMessage());
        info.put("time", LocalDateTime.now());
        returninfo;
    }

3.5、启动项目,进行测试,访问http://127.0.0.1:9090/users/40,并填写正确的用户名密码

API安全(八)-审计第3张

执行顺序如下

API安全(八)-审计第4张

数据库审计日志表

API安全(八)-审计第5张

准备一个有错误的方法

    @DeleteMapping("/{id}")
    public voiddelete(@PathVariable Long id){
        int i = 1 / 0;
    }

测试如下:

API安全(八)-审计第6张

数据库审计日志表

API安全(八)-审计第7张

3.6、如果想基于Interceptors来实现,做如下修改

3.6.1、AuditLogInterceptor拦截器

/*** 基于Interceptor的审计拦截器 ,与AuditLogFilter同时只能使用一个
 *
 * @authorcaofanqi
 * @date 2020/1/28 23:12
 */@Slf4j
@Component
public class AuditLogInterceptor extendsHandlerInterceptorAdapter {


    @Resource
    privateAuditLogRepository auditLogRepository;


    @Override
    public booleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        log.info("++++++3、审计++++++");

        AuditLogDO auditLogDO = newAuditLogDO();
        auditLogDO.setHttpMethod(request.getMethod());
        auditLogDO.setPath(request.getRequestURI());

        auditLogRepository.save(auditLogDO);

        request.setAttribute("auditLogId",auditLogDO.getId());

        return true;
    }


    @Override
    public voidafterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex){
        Long auditLogId = (Long) request.getAttribute("auditLogId");

        AuditLogDO auditLogDO = auditLogRepository.findById(auditLogId).orElse(newAuditLogDO());
        auditLogDO.setHttpStatus(response.getStatus());

        auditLogRepository.save(auditLogDO);

    }

}

3.6.2、注册拦截器

/*** web配置类
 *
 * @authorcaofanqi
 * @date 2020/1/28 22:32
 */@Configuration
public class WebConfig implementsWebMvcConfigurer {


    @Resource
    privateAuditLogInterceptor auditLogInterceptor;

    /*** 注册拦截器
     */@Override
    public voidaddInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(auditLogInterceptor);
    }

}

3.6.3、进行3.5的测试效果相同

项目源码:https://github.com/caofanqi/study-security/tree/dev-auditing

免责声明:文章转载自《API安全(八)-审计》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇在Ubuntu-14.04.3配置并成功编译Android6_r1源码死性不改【16Q4】ISO9000 Win7x64专业版、Windows Server 2008r2企业版下载下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python源代码安全审计工具之Bandit

Bandit是一种旨在查找Python代码中常见安全问题的工具。 它处理每个文件 从中构建AST 然后针对AST节点运行适当的插件。 当它扫描完成所有文件之后将生成报告。 以下安装部署过程基于Windows操作系统,假设已经安装并设置好了以下软件。 "Python 3.7.8 AMD64" "64-bit Git for Windows" 最便捷的安装方式...

等保2.0 二级安全要求

等保2.0二级安全要求 第二级安全保护能力:应能够防护免受来自外部小型组织的、拥有少量资源的威胁源发起的恶意攻击、一般的自然灾害,以及其他相当危害程度的威胁所造成的重要资源损害,能够发现重要的安全漏洞和处置安全事件,在自身遭到损害后,能够在一段事件内恢复部分功能。 以下加粗字段为等保二级与一级的区别,需重点关注。 1安全通用要求 1.1安全物理环境 1....

信息安全等级保护三级系统基线要求判分标准之应用安全

条款理解可参考:https://wenku.baidu.com/view/26c447385727a5e9856a618a.html 原文链接:https://www.cnblogs.com/xiaozi/p/5912009.html 针对等级保护三级系统的防护要求,对于应用安全涉及的“身份鉴别”、“访问控制”、“安全审计”、“剩余信息保护”、“通信完整性...

等保测评windows主机加固

控制点 安全要求 要求解读 测评方法 预期结果或主要证据 身份鉴别 a)应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换 用户的身份标识和鉴别,就是用户向操作系统以一种安全的方式提交自己的身份证实,然后由操作系统确认用户的身份是否属实的过程,身份标识要求具有唯一性。在用户进入Windows桌面前,如果弹出...

Go源代码安全审计工具之gosec

gosec分析Go源代码以查找可能导致安全问题的常见编程错误。 它通过扫描Go AST检查源代码是否存在安全问题。 https://github.com/securego/gosec gosec v2.4.0 gosec - Golang security checker gosec analyzes Go source code to look for...

等保2.0四级安全要求

等保2.0四级安全要求 第四级安全保护能力:应能够在统一安全策略下防护免受来自国家级别的、敌对组织的、拥有丰富资源的威胁源发起的恶意攻击、严重的自然灾害,以及其他相当危害程度的威胁所造成的资源损害,能够及时发现、监测发现攻击行为和安全事件,在自身遭到损害后,能够迅速恢复所有功能。 以下加粗字段为等保四级与三级的区别,需重点关注。 1安全通用要求 1.1安...