Используя новый spring-authorization-server 0.2.3 и следуя https://github.com/spring-projects/spring-authorization-server/tree/main/samples в качестве ссылки, я смог успешно настроить сервер авторизации, сервер ресурсов и клиент при использовании InMemoryUserDetailsManager
следующим образом.
@EnableWebSecurity
public class DefaultSecurityConfig {
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeRequests(authorizeRequests ->
authorizeRequests.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}
@Bean
UserDetailsService users() {
User.UserBuilder users = User.withDefaultPasswordEncoder();
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(users.username("user1").password("password").roles("USER").build());
manager.createUser(users.username("admin").password("password").roles("USER", "ADMIN").authorities("r1","r2","r3").build());
return manager;
}
}
Это хорошо работает. В клиенте я вижу присутствие властей Granted Authorities=["r1","r2","r3"]
.
Теперь, когда я пытаюсь реализовать свой собственный UserDetailsService
, который извлекает пользователей из базы данных Mongo, я перестаю видеть передачу GrantedAuthorities клиенту и вижу только Granted Authorities=[ROLE_USER, SCOPE_openid]
Это то, что у меня сейчас есть в DefaultSecurityConfig
@EnableWebSecurity
public class DefaultSecurityConfig {
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeRequests(authorizeRequests ->
authorizeRequests.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}
@Autowired
private MongoTemplate mongoTemplate;
@Bean
UserDetailsService users() {
return new CustomUserDetailsService(mongoTemplate);
}
}
И мой CustomUserDetailsService
выглядит следующим образом:
public class CustomUserDetailsService implements UserDetailsService {
private final MongoTemplate mongoTemplate;
public CustomUserDetailsService(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Criteria criteria = Criteria.where("email").is(username);
CustomUser user = mongoTemplate.findOne(new Query(criteria), CustomUser.class, "vOAuthUser");
if (user != null) {
log.info("Found user {}", user.email());
List<GrantedAuthority> authorities = getUserAuthority(user.groups());
return buildUserForAuthentication(user, authorities);
} else {
throw new UsernameNotFoundException("username not found");
}
}
private UserDetails buildUserForAuthentication(CustomUser user, List<GrantedAuthority> authorities) {
return new org.springframework.security.core.userdetails.User(user.email(), user.password(), authorities);
}
private List<GrantedAuthority> getUserAuthority(Set<String> groups) {
List<GrantedAuthority> authorities = new ArrayList<>();
groups.forEach(s -> {
Criteria criteria = Criteria.where("name").is(s);
CustomRole role = mongoTemplate.findOne(new Query(criteria), CustomRole.class, "vRole");
if (role != null) {
authorities.addAll(role.grantedAuthorities());
}
});
return authorities;
}
}
Any help is greatly appreciated.
Вы определили bean-компонент OAuth2TokenCustomizer в своей конфигурации безопасности? Вы можете добавить предоставленные полномочия туда, если вам нужно, как в следующем коде:
@Bean
@SuppressWarnings("unused")
OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
return context -> {
JoseHeader.Builder headers = context.getHeaders();
JwtClaimsSet.Builder claims = context.getClaims();
Authentication principal = context.getPrincipal();
Set<String> authorities = principal.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toSet());
claims.claim("authorities", authorities);
};
}
Может быть, это поможет stackoverflow.com/questions/59379645/…
Работает хорошо, спасибо. Есть ли способ сопоставить утверждения ["полномочия"] от принципала oidc с корневой аутентификацией
getAuthorities()
, поскольку я хочу использовать авторизацию метода Pre/Post в моем клиенте.