Jhipster 微服务 - 在微服务中获取 UserId 的正确方法?
Jhipster Microservices - Correct way to get UserId in Microservices?
我正在将 JHipster 的网关与 JWT 一起使用,并且我有一个微服务。
当rest调用从网关转发到微服务时,在微服务业务class中,我想获取认证用户的用户id。
这样做的原因是我想将它与实体一起保存在数据库中,以便一个用户的数据可以与其他用户的数据完全分开(并且一个用户不能更新另一个用户的数据......等等......) .
虽然我可以得到登录的用户名,但我没有用户id。
解决这个问题的正确方法是什么:
- 从微服务调用网关?
(这对我来说意义不大,因为网关正在调用该服务,我想知道大多数服务的此信息)。
更新网关中的 TokenProvider 以包含用户 ID? (不确定该怎么做)。这是正确的做法吗?
还有其他建议吗?
谢谢,
弗加尔.
注:我看到其他类似的问题。这不是一个重复的问题。除非绝对确定,否则不要将此标记为重复。注意 - 我正在使用 JWT
为了解决这个问题,我在网关的令牌中添加了用户 ID 到每个微服务。
以下是我在 JHipster 生成的代码中解决这个问题的方法:
在Gateway中,将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";
然后在我的 微服务应用程序 中,我这样做了:
创建了一个新的 class:
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;
});
}
最后,我现在可以从任何企业调用此方法 class:
Optional<Long> userId = SecurityUtils.getUserId();
if (userId.isPresent()) {
log.info("User Id--->{}", userId.get());
} else {
log.info("No userId present.");
}
欢迎任何反馈。
我正在将 JHipster 的网关与 JWT 一起使用,并且我有一个微服务。
当rest调用从网关转发到微服务时,在微服务业务class中,我想获取认证用户的用户id。
这样做的原因是我想将它与实体一起保存在数据库中,以便一个用户的数据可以与其他用户的数据完全分开(并且一个用户不能更新另一个用户的数据......等等......) .
虽然我可以得到登录的用户名,但我没有用户id。
解决这个问题的正确方法是什么:
- 从微服务调用网关?
(这对我来说意义不大,因为网关正在调用该服务,我想知道大多数服务的此信息)。
更新网关中的 TokenProvider 以包含用户 ID? (不确定该怎么做)。这是正确的做法吗?
还有其他建议吗?
谢谢, 弗加尔.
注:我看到其他类似的问题。这不是一个重复的问题。除非绝对确定,否则不要将此标记为重复。注意 - 我正在使用 JWT
为了解决这个问题,我在网关的令牌中添加了用户 ID 到每个微服务。
以下是我在 JHipster 生成的代码中解决这个问题的方法:
在Gateway中,将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";
然后在我的 微服务应用程序 中,我这样做了:
创建了一个新的 class:
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;
});
}
最后,我现在可以从任何企业调用此方法 class:
Optional<Long> userId = SecurityUtils.getUserId();
if (userId.isPresent()) {
log.info("User Id--->{}", userId.get());
} else {
log.info("No userId present.");
}
欢迎任何反馈。