SpringCloud微服务安全API安全 2-6 审计
Posted 鮀城小帅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud微服务安全API安全 2-6 审计相关的知识,希望对你有一定的参考价值。
1. 补充:如何保证API安全的请求流程
当前已经有了流控、认证,但是它们并没有按照要求进行顺序执行。
我们要求先执行流控,然后再执行认证。
解决方案: 使用 @Order注解
流控:
认证:
2. 审计日志
2.1 审计说明
审计日志
定义:谁,在什么时间,干了什么事。
位置:认证之后,授权之前。
这样就知道是谁在访问,拒绝掉的访问也能被记录。如果放在认证之前,那么就不知道是谁在访问;如果放在授权之后,就没办法记录被拒绝的访问。
存储:审计日志一定要持久化,记在数据库里或者是文件,放在内存会丢失。(输出到公司的日志服务)
怎么记:请求进来的时候记录一次,请求出去的时候,更新日志。
如果只在请求进来的时候记,那么请求的成功与否是不知道的。如果只在请求返回的时候记,那么如果一个请求把你的系统搞挂了,也没有记,是不知道谁搞挂的。
技术选择:过滤器 VS 拦截器 VS ControllerAdvice VS AOP
选择的原因:
- 过滤器,不好分辨是请求过来执行的还是请求出去执行的; ControllerAdvice-做全局异常处理 ;AOP -不说了
- 就用拦截器,拦截器在过滤器之后执行。
3. 审计功能
3.1 创建审计日志类
package com.imooc.security.log;
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.util.Date;
/**
* @ClassName AuditLog
* @Description TODO 审计日志
* @Author wushaopei
* @Date 2021/5/1 17:56
* @Version 1.0
*/
@Entity
@Data
@EntityListeners(AuditingEntityListener.class) // 注入审计监听器
public class AuditLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String method;
private String path;
private Integer status;
private String username;
@Temporal(TemporalType.TIMESTAMP)
@CreatedDate
private Date createTime;
@Temporal(TemporalType.TIMESTAMP)
@CreatedDate
private Date modifyTime;
}
这里需要从Java实体反向生成数据库对应的表,需要保证在application.yml中添加以下配置:
jpa:
generate-ddl: true #控制是否执行datasource.schema脚本,来初始化数据库结构
show-sql: true
3.2 创建审计拦截器
package com.imooc.security.filter;
import com.imooc.security.log.AuditLog;
import com.imooc.security.log.AuditLogRepository;
import com.imooc.security.user.User;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @ClassName AuditLogInterceptor
* @Description TODO 审计日志拦截器
* @Author wushaopei
* @Date 2021/5/1 18:02
* @Version 1.0
*/
@Component
public class AuditLogInterceptor extends HandlerInterceptorAdapter {
@Autowired
private AuditLogRepository auditLogRepository;
/**
* @Description TODO 前置处理,请求进来就进行记录
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
AuditLog log = new AuditLog();
log.setMethod(request.getMethod());
log.setPath(request.getRequestURI());
User user = (User)request.getAttribute("user");
if (user != null){
log.setUsername(user.getUsername());
}
auditLogRepository.save(log);
request.setAttribute("auditLogId", log.getId());
return true;
}
/**
* @Description TODO 后置处理,请求返回的时候进行记录
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
Long auditLogId = (Long)request.getAttribute("auditLogId");
AuditLog log = auditLogRepository.findById(auditLogId).get();
log.setStatus(response.getStatus());
auditLogRepository.save(log);
}
}
3.3 注册审计拦截器
@Configuration
@EnableJpaAuditing //JPA审计的总开关
public class SecurityConfig implements WebMvcConfigurer {
@Autowired
private AuditLogInterceptor auditLogInterceptor;
/**
* @Description TODO 将审计拦截器添加到mvc容器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(auditLogInterceptor);
}
}
3.4 创建审计类写入DB的类 AuditLogRepository.java
public interface AuditLogRepository extends JpaSpecificationExecutor<User>,CrudRepository<AuditLog,Long> {
}
3.5 启动程序自动生成 audit_log 表
3.6 发起请求,拦截器拦截请求并记录到审计日志中
记录审计日志:
3.7 新增异常处理器
解决SpringBoot抛出异常后,会跳到一个/error 的路径。然后将 error 记录到审计日志的问题。
package com.imooc.security.filter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName ErrorHandler
* @Description TODO 异常处理类
* @Author wushaopei
* @Date 2021/5/1 18:33
* @Version 1.0
*/
@RestControllerAdvice
public class ErrorHandler {
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
public Map<String, Object> handler(Exception e){
Map<String, Object> info = new HashMap<>();
info.put("message", e.getMessage());
info.put("time",new Date().getTime());
return info;
}
}
返回异常处理信息给前端:
以上是关于SpringCloud微服务安全API安全 2-6 审计的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud微服务安全API安全 2-2 注入攻击防护
SpringCloud微服务安全实战API安全 3-9 总结