Я использую шлюз JHipster с JWT, и у меня есть микросервис.
Когда остальной вызов перенаправляется со шлюза на микросервис в бизнес-классе микросервиса, я хочу получить идентификатор пользователя, прошедшего проверку подлинности.
Причина этого в том, что я хочу сохранить его в базе данных вместе с объектом, чтобы данные одного пользователя могли быть полностью отделены от данных другого пользователя (и пользователь не мог обновлять данные другого пользователя ... и т. д.).
Хотя я могу получить имя пользователя, вошедшего в систему, у меня нет идентификатора пользователя.
Каков правильный подход к решению этой проблемы:
(для меня это не имеет особого смысла, поскольку шлюз вызывает службу, и я хочу знать эту информацию для большинства служб).
обновить TokenProvider в шлюзе, чтобы включить идентификатор пользователя? (не знаю, как это сделать). Это правильный подход?
любые другие предложения?
Спасибо, Фергал.
Примечание: я вижу другие похожие вопросы. Это не повторяющийся вопрос. Не отмечайте это как дубликат, если нет полной уверенности. Примечание. Я использую JWT.
Спасибо @ GaëlMarziou. Я разместил свой код, чтобы он мог помочь другим. Любые отзывы о моем подходе приветствуются.
Хорошая работа. Спасибо, что опубликовали свой код .. Кстати, вы забыли "t" в Authenication в SamAuthenicationToken





Чтобы решить эту проблему, я добавил идентификатор пользователя в токен от шлюза для каждого микросервиса.
Вот как я решил это в сгенерированном коде JHipster:
В шлюзе, добавьте UserService в UserJWTController и получите идентификатор пользователя, и используйте его при создании токена.
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)
обратите внимание, я добавил это в Token Provider:
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;
});
}
и, наконец, теперь я могу вызвать этот метод из любого бизнес-класса:
Optional<Long> userId = SecurityUtils.getUserId();
if (userId.isPresent()) {
log.info("User Id--->{}", userId.get());
} else {
log.info("No userId present.");
}
Любая обратная связь приветствуется.
Почему вы выбрали для этого шлюз?
@ddsultan - шлюз является наиболее подходящим местом для этого, поскольку это то, что нужно многим службам, стоящим за шлюзом. Если заставить шлюз делать это, каждая служба не должна делать себя сама ... как видите, это очень небольшое изменение для шлюза, но очень полезное. Я использовал ISAM (IBM Security and Access Mgt) в проекте, и их обратный прокси-сервер делает именно это.
@fergal_dd большое спасибо! Ваша реализация мне очень помогла !!!
Я бы обновил TokenProvider, заменив тему или добавив утверждение для идентификатора пользователя.