首页 > 解决方案 > 如何在 Spring Boot 的每个请求中获取当前用户?

问题描述

我想在每个请求中获取用户的用户名,以将它们添加到日志文件中。

这是我的解决方案:

LoggedUser首先,我用一个属性创建了一个static

public class LoggedUser {

    private static final ThreadLocal<String> userHolder = 
        new ThreadLocal<>();

    public static void logIn(String user) {
        userHolder.set(user);
    }

    public static void logOut() {
        userHolder.remove();
    }

    public static String get() {
        return userHolder.get();
    }
}

然后我创建了一个支持类来获取用户名:

public interface AuthenticationFacade {
    Authentication getAuthentication();
}
@Component
public class AuthenticationFacadeImpl implements AuthenticationFacade {
    @Override
    public Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }
}

最后,我在控制器中使用了它们:

    @RestController
    public class ResourceController {

        Logger logger = LoggerFactory.getLogger(ResourceController.class);

        @Autowired
        private GenericService userService;
        @Autowired
        private AuthenticationFacade authenticationFacade;

        @RequestMapping(value ="/cities")
        public List<RandomCity> getCitiesAndLogWhoIsRequesting(){
        loggedUser.logIn(authenticationFacade.getAuthentication().getName());
        logger.info(LoggedUser.get()); //Log username
        return userService.findAllRandomCities();
        }
    }

问题是我不想AuthenticationFacade在每一个中都有@Controller,例如,如果我有 10000 个控制器,那将是很多工作。

你有什么更好的解决方案吗?

标签: javaspringspring-mvcspring-boot

解决方案


该解决方案称为Fish Tagging。每个像样的日志框架都有这个功能。一些框架称之为MDC(映射诊断上下文)。你可以在这里这里阅读。

基本思想是在线程中使用ThreadLocalInheritableThreadLocal保存一些键值对来跟踪请求。使用日志配置,您可以配置如何在日志条目中打印它。

基本上,您可以编写一个过滤器,您可以在其中从安全上下文中检索用户名并将其放入,MDC然后忘记它。在您的控制器中,您只记录与业务逻辑相关的内容。用户名将与时间戳、日志级别等一起打印在日志条目中(根据您的日志配置)。


推荐阅读