Я хочу реализовать безопасность на своем сервере облачного шлюза Spring, сделав его сервером ресурсов oAuth2. Запросы аутентифицируются на моем сервере авторизации безопасности Spring. Для некоторых запросов я хочу передать userId аутентифицированного пользователя в качестве заголовка запроса моим нижестоящим службам.
Вот мой маршрут:
.route("create-deck", routeSpec -> routeSpec
.path("/decks")
.and()
.method(HttpMethod.POST)
.filters(
fs -> fs.addRequestHeader("userId", "ADD_USER_ID_HEADER_HERE"))
.uri("http://localhost:8082/"))
Я настроил свой сервер авторизации для возврата userId в качестве основного имени:
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = ur.findByUsername(username);
if (user == null) {
log.error("User: {} not found", username);
throw new UsernameNotFoundException("User: " + username + " not found");
}
return new org.springframework.security.core.userdetails.User(String.valueOf(user.getId()), user.getPassword(), authorities);
}
Примечание. У меня есть пользовательский объект домена User, который я храню в своей базе данных.
Маршрут успешно аутентифицируется, и токен содержит идентификатор пользователя в качестве субъекта. Мне просто нужна помощь в том, как получить тему и передать ее моему нисходящему запросу в качестве заголовка запроса.
Я использую следующие зависимости:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.6.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>





Вы можете создать собственный фильтр, который будет применяться ко всем запросам. Вот пример, когда user является частью токена jwt.
public class UserHeaderFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return ReactiveSecurityContextHolder.getContext()
.filter(c -> c.getAuthentication() != null)
.flatMap(c -> {
JwtAuthenticationToken jwt = (JwtAuthenticationToken) c.getAuthentication();
String user = (String) jwt.getTokenAttributes().get("user");
if (Strings.isNullOrEmpty(user)) {
return Mono.error(
new AccessDeniedException("Invalid token. User is not present in token.")
);
}
ServerHttpRequest request = exchange.getRequest().mutate()
.header("x-user", user).build();
return chain.filter(exchange.mutate().request(request).build());
})
.switchIfEmpty(chain.filter(exchange));
}
}
Я думал, что это может быть решением проблемы, но ваш ответ помог, и он работает. Большое спасибо!