在Spring Spring Preututize on controller之后使用AspectJ进行审计

时间:2016-12-08 14:08:52

标签: java spring spring-security aop audit

我试图在Spring应用程序中审核日志成功和失败的OAuth2身份验证尝试。我正在使用Spring的@PreAuthorize注释,如下所示。


checkout([$class: 'GitSCM', ...])

身份验证和授权正常。在尝试进行审计​​日志记录时,我尝试使用AspectJ进行一些AOP,如下所示。

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@PreAuthorize("#oauth2.hasScope('read')")
public Person getById(@PathVariable String id) {
    return service.getById(id);
}

但是,只有在身份验证和授权都成功时才会受到影响。这些是场景:

  • 给定具有读取范围的有效令牌 - afterAuth命中
  • 鉴于无效令牌 - afterAuth未命中
  • 给定没有读取范围的有效令牌 - afterAuth not hit

我最好的猜测是,当身份验证或授权失败时,Spring会采取不同的做法,但我不确定如何解决这个问题。有什么建议吗?

1 个答案:

答案 0 :(得分:0)

无法找到在一个文件中执行此操作的好方法,因此我最终使用一个文件来处理失败的身份验证请求(使用事件),另一个文件处理成功的身份验证请求(使用方面)。我使用自定义MyAnnotation注释了所有控制器,其中包含有关控制器的一些信息。这可能不是最好的解决方案,但希望它可以帮助某人。

失败:

@Component
public class FailedAuthRequestAuditor {

    private ApplicationContext context;
    private AuditEventLogger logger;

    @Autowired
    public FailedAuthRequestAuditor(
        ApplicationContext context,
        AuditEventLogger logger
    ) {
        this.context = context;
        this.logger = logger;
    }

    @EventListener
    public void onBadCredentialsEvent(AuthenticationFailureBadCredentialsEvent event) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Method destinationMethod = this.getDestination(request);

        if (destinationMethod != null) {
            // do logging here
        }
    }

    @EventListener
    public void onAuthorizationFailureEvent(AuthorizationFailureEvent event) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Method destinationMethod = this.getDestination(request);

        if (destinationMethod != null) {
            // do logging here
        }
    }


    private Method getDestination(HttpServletRequest request) {
        for (HandlerMapping handlerMapping : context.getBeansOfType(HandlerMapping.class).values()) {
            HandlerExecutionChain handlerExecutionChain = null;
            try {
                handlerExecutionChain = handlerMapping.getHandler(request);
            } catch (Exception e) {
                // do nothing
            }

            if (handlerExecutionChain != null && handlerExecutionChain.getHandler() instanceof HandlerMethod) {
                return ((HandlerMethod) handlerExecutionChain.getHandler()).getMethod();
            }
        }

        return null;
    }

}

成功:

@Aspect
@Component
public class SuccessfulAuthRequestAuditor {

    private AuditEventLogger auditEventLogger;
    private AuditEventOutcomeMapper mapper;

    @Autowired
    public SuccessfulAuthRequestAuditor(AuditEventLogger auditEventLogger, AuditEventOutcomeMapper mapper) {
        this.auditEventLogger = auditEventLogger;
        this.mapper = mapper;
    }

    @AfterReturning(pointcut = "execution(@com.company.MyAnnotation * *(..)) && @annotation(myAnnotation) && args(request,..)", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result, MyAnnotation myAnnotation, HttpServletRequest request) {
        // do logging
    }

    @AfterThrowing(pointcut = "execution(@com.company.MyAnnotation * *(..)) && @annotation(myAnnotation) && args(request,..)", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Throwable exception, MyAnnotation myAnnotation, HttpServletRequest request) {
        // do logging
    }
}