如何通过 MDC 将从 JWT 获取的用户 ID 添加到后端日志?

Posted

技术标签:

【中文标题】如何通过 MDC 将从 JWT 获取的用户 ID 添加到后端日志?【英文标题】:How to add user id taken from JWT to the backend logs via MDC? 【发布时间】:2021-02-27 14:27:47 【问题描述】:

我们有一个带有 REST 接口和 Web 客户端的 Spring Boot 应用程序。我们使用带有 OAuth 2.0 JWT 令牌的 spring-security 进行身份验证。我们使用 slf4j 和 sleuth 进行日志记录。我们想在日志中记录当前登录的用户 ID。从技术上讲,我们希望将用户 ID 添加到服务器应用程序的映射诊断上下文 (MDC)

目标是将前端操作导致的服务器端错误链接到触发后端操作的用户。

目前,我们在客户端提取用户ID,并将ID作为HTTP头字段发送到服务器,在那里它被侦探从HTTP头中作为行李提取并添加到日志中,请参见以下spring.sleuth.baggage配置。这是有效的。

spring.sleuth.baggage.remote-fields=user_id
spring.sleuth.baggage.tag-fields=user_id
spring.sleuth.baggage.correlation-fields=user_id

用户由user=%Xuser_id:-登录,查看完整的日志模式:

logging:
  level:
    ROOT: WARN
  pattern:
    console: "[%d] [%t] %highlight(%-5p) %c10 - %cyan([trace=%XX-B3-TraceId:- span=%XX-B3-SpanId:- user=%Xuser_id:-]) %m%n"

但是,我们希望在服务器端直接从 JWT 令牌中提取用户 ID,而不是在客户端提取用户 id 并将其发送到后端。因为所有信息也可以直接在服务器端获得。

我查看了 spring-cloud-sleuth 文档如何在 Java 中设置行李字段,但我不知道该怎么做。

https://cloud.spring.io/spring-cloud-sleuth/reference/html/#java-configuration https://docs.spring.io/spring-cloud-sleuth/docs/current-SNAPSHOT/reference/html/project-features.html#features-brave-baggage https://docs.spring.io/spring-cloud-sleuth/docs/current-SNAPSHOT/reference/html/appendix.html#appendix

我不知道要使用哪些类以及如何使用它们。我试过下面的代码。代码在 Spring 启动时不执行。因此,似乎缺少某些配置或代码完全错误。

package net.company.common.service;

import brave.baggage.BaggageField;
import brave.baggage.BaggagePropagation;
import brave.baggage.BaggagePropagationConfig;
import brave.baggage.BaggagePropagationCustomizer;
import brave.internal.baggage.BaggageContext;
import net.company.common.service.CommonServiceConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan
@Import(CommonServiceConfig.class)
public class ServiceConfig 

  @Bean
  BaggagePropagationConfig.SingleBaggageField singleBaggageField() 
    BaggagePropagationConfig.SingleBaggageField field = BaggagePropagationConfig.SingleBaggageField.newBuilder(BaggageField.create("user_id")).build();
    field.field().updateValue("user_12345"); // set only dummy value for debug
    return field;
  


可以手动实现这样的 MDC,请参阅 https://www.baeldung.com/mdc-in-log4j-2-logback。但由于这很容易出错,我们希望避免它,例如上下文清理必须正确完成。

如何使用 sleuth/brave 将来自 JWT 的用户 ID 添加到 MDC 以进行服务器端日志记录?

【问题讨论】:

【参考方案1】:

既然你正在使用

spring.sleuth.baggage.remote-fields=user_id

它对你有用,这就是如何创建和更新 Baggage Fields 的值。

    BaggageField baggageField = BaggageField.create(baggageKey);
    baggageField.updateValue(baggageValue);

请注意,以这种方式更新行李价值将显示在下一个跨度的日志中。如果您想更新同一跨度中的值,请查看此答案https://***.com/a/67373784/2224254

【讨论】:

【参考方案2】:

我正在使用

spring boot version: 2.1.2.RELEASE
spring cloud version: Greenwich.RELEASE

您可以使用以下属性进行配置

spring.sleuth.propagation-keys=user_id
spring.sleuth.log.slf4j.whitelisted-mdc-keys=user_id

【讨论】:

以上是关于如何通过 MDC 将从 JWT 获取的用户 ID 添加到后端日志?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 jwt 令牌中获取用户 ID?

如何从 JWT 令牌中获取用户 ID

如何使用 jwt 令牌获取用户 ID

如何使用 jwt 令牌获取用户 ID

如何在 mongodb 中获取用户 id 并在 jwt 中使用它?

Slf4j日志添加用户id,reqId等信息