Jhipster微服务-在微服务中获取UserId的正确方法?

时间:2018-10-31 10:28:13

标签: jhipster

我在JWT上使用JHipster的网关,并且有一个微服务。

当其余调用从网关转发到微服务时,在微服务业务类中,我想获取经过身份验证的用户的用户ID。

这样做的原因是我想将它与实体一起保存在数据库中,以便一个用户的数据可以与另一个用户的数据完全分开(并且一个用户不能更新另一个用户的数据...等。)。 / p>

虽然我可以获取登录的用户名,但没有用户ID。

解决此问题的正确方法是什么?

  • 从微服务中调用网关吗?

(这对我来说没有太大意义,因为网关正在调用该服务,并且我想了解大多数服务的此信息)。

  • 更新网关中的TokenProvider以包括用户ID? (不确定如何执行此操作)。这是正确的方法吗?

  • 还有其他建议吗?

谢谢, Fergal。

注意:我看到其他类似的问题。这不是重复的问题。除非绝对确定,否则请勿将其标记为重复项。注意-我正在使用JWT

1 个答案:

答案 0 :(得分:4)

为解决此问题,我在令牌中从网关向每个微服务添加了用户ID。

这是我在JHipster生成的代码中解决此问题的方法:

在网关中,将UserService添加到UserJWTController,并获取用户ID,然后 创建令牌时使用它。

public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginVM loginVM) {
    ...
    ...
    Optional<User> user = userService.getUserWithAuthoritiesByLogin(loginVM.getUsername());
    Long userId = user.get().getId();
    String jwt = tokenProvider.createToken(authentication, rememberMe, userId);
    ...

将声明添加到令牌中:

  claim(USER_ID_KEY, userId)

请注意,我已将此添加到令牌提供者:

  private static final String USER_ID_KEY = "userId";

,然后在我的微服务应用程序中,执行此操作:

创建了一个新类:

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;

public class SamAuthenticationToken extends UsernamePasswordAuthenticationToken {

public Long getUserId() {
    return userId;
}

private final Long userId;

public SamAuthenticationToken(Object principal, Object credentials, Long userId) {
    super(principal, credentials);
    this.userId = userId;
}

public SamAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities, Long userId) {
    super(principal, credentials, authorities);
    this.userId = userId;
}
}

然后我更改了TokenProvider.getAuthentication以添加以下行:

    Long userId = null;
    Object userIdObj = claims.get(USER_ID_KEY);
    if (userIdObj != null) {
        String userIdStr = userIdObj.toString();
        userId = Long.parseLong(userIdStr);
        log.debug("Claim--> {}", userId);
    } else {
        log.debug("No user id in token");
    }

    User principal = new User(claims.getSubject(), "", authorities);
    return new SamAuthenticationToken(principal, token, authorities, userId);

然后我向SecurityUtils添加了一种新方法

 public static Optional<Long> getUserId() {
    SecurityContext securityContext = SecurityContextHolder.getContext();
    return Optional.ofNullable(securityContext.getAuthentication())
        .map(authentication -> {
            if (authentication instanceof SamAuthenticationToken) {
                SamAuthenticationToken samAuthenticationToken = (SamAuthenticationToken) authentication;
                return samAuthenticationToken.getUserId();
            }
            return null;
        });
 }

最后,我现在可以从任何Business类调用此方法:

    Optional<Long> userId = SecurityUtils.getUserId();
    if (userId.isPresent()) {
        log.info("User Id--->{}", userId.get());
    } else {
        log.info("No userId present.");
    }

欢迎任何反馈。