在Spring AOP方面从Sring Security获取用户身份验证的正确解决方案是什么?

问题描述 投票:0回答:1

我有一个方面可以审计实体的创建、删除等。在审计中我必须获取触发实体更改的用户。

package com.sdx.rootservice.auditing.aspect;

import com.sdx.rootservice.auditing.model.AuditType;
import com.sdx.rootservice.auditing.service.interfaces.AuditLogService;
import com.sdx.rootservice.dto.lead.AppealTypeDto;
import com.sdx.rootservice.security.model.JwtAuthentication;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Component
@Aspect
@Log4j2
@RequiredArgsConstructor
public class AuditAspect {

    private final AuditLogService auditLogService;

    @AfterReturning(pointcut = "execution(* com.sdx.rootservice.controller.company.AppealTypeController.create(..))",
            returning = "appealTypeDto")
    public void afterAppealTypeCreated(AppealTypeDto appealTypeDto) {
        var userId = fetchUserId();
        var targetId = appealTypeDto.getId();
        log.debug("Created new appeal type: " + appealTypeDto);
        auditLogService.logChanges(userId, "AppealType", targetId, AuditType.CREATE);
    }

    @AfterReturning(pointcut = "execution(* com.sdx.rootservice.controller.company.AppealTypeController.delete(..)) && args(id)")
    public void afterAppealTypeDeleted(Long id) {
        var userId = fetchUserId();
        log.debug("Deleted new appeal type: " + id);
        auditLogService.logChanges(userId, "AppealType", id, AuditType.DELETE);
    }

    private Long fetchUserId() {
        var authentication = (JwtAuthentication) SecurityContextHolder.getContext().getAuthentication();
        return Optional.ofNullable(authentication)
                .map(JwtAuthentication::getId)
                .orElse(null);
    }
}

恐怕,如果有多个创建端点的请求,安全性的上下文可能会发生变化,因为将运行不同的线程。在Spring AOP方面从Sring Security获取用户身份验证的正确解决方案是什么?

java spring spring-security spring-aop
1个回答
0
投票

只要您不通过将系统属性

SecurityContextHolderStrategy
更改为
GlobalSecurityContextHolderStrategy
来将默认的
spring.security.strategy
更改为
MODE_GLOBAL
,并且可以确保
AuditAspect
将由受保护的 URL 调用spring security,你不需要担心它,因为 spring security 将确保当它完成处理 HTTP 请求时,它总是会清除
SecurityContext

在代码中,这是由

FilterChainProxy#doFilter()
的finally块在here完成的。

© www.soinside.com 2019 - 2024. All rights reserved.