Я бы предложил использовать jwt токен , который прикрепляется к каждому запросу к вашему бэкэнду в качестве заголовка «Авторизация». Маркер состоит из трех частей: одна содержит данные о пользователе, а другая - подпись, поэтому вы можете проверить, что ваш токен был создан из надежного источника. Часть данных может выглядеть примерно так:
{
"iss": "Online JWT Builder",
"iat": 1580283510,
"exp": 1611819510,
"aud": "www.example.com",
"sub": "jrocket@example.com",
"GivenName": "Johnny",
"roles": ["PROJECT_MANAGER", "ADMIN"]
"scope": "WEBAPP"
}
Со стороны Spring я бы предложил использовать Spring Security 5 с последней конфигурацией. Вам понадобятся эти зависимости:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.x.x.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.x.x.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
<version>5.x.x.RELEASE</version>
Теперь вы можете включить защиту и настроить ее с помощью класса конфигурации. Внутри вы можете определить, какая область должна быть в запросе, как подписать токен и маршрут должен быть опубликован c или защищен.
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
String jwkSetUri;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.cors().disable()
.authorizeRequests()
.antMatchers(("/webapp/**")).hasAuthority("SCOPE_WEBAPP")
.antMatchers(("/admin/**")).hasRole("ADMIN")
...
.and()
.oauth2ResourceServer().jwt(jwtConfigurer -> jwtConfigurer.decoder(jwtDecoder())
.jwtAuthenticationConverter(new CustomJwtAuthenticationConverter()))
...
// @formatter:on
}
@Bean
JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
}
}
Мне пришлось использовать пользовательский JwtConverter для получения ролей из JWT, но это зависит от того, как вы это делаете, я думаю.
public class CustomJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {
private final JwtGrantedAuthoritiesConverter defaultGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
public CustomJwtAuthenticationConverter() {
}
@Override
public AbstractAuthenticationToken convert(@NotNull final Jwt jwt) {
Collection<GrantedAuthority> authorities = Stream
.concat(defaultGrantedAuthoritiesConverter.convert(jwt).stream(), extractResourceRoles(jwt).stream())
.collect(Collectors.toSet());
return new JwtAuthenticationToken(jwt, authorities);
}
private static Collection<? extends GrantedAuthority> extractResourceRoles(final Jwt jwt) {
Collection<String> userRoles = jwt.getClaimAsStringList("roles");
if (userRoles != null)
return userRoles
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toSet());
return Collections.emptySet();
}
}
Это позволяет вам защитить свое приложение на основе URL.
Роли в jwt, JwtConverter и аннотация @EnableGlobalMethodSecurity
позволяет защитить даже на уровне метода .
@Transactional
@PreAuthorize("hasRole('ROLE_PROJECT_MANAGER')")
public Page<Project> findAll(Pageable pageable) {
return projectRepository.findAll(pageable);
}
Azure Active Directory должна поддерживать jwt , но у меня нет опыта работы с этим IDP. Что я не могу ответить, так это то, как вы можете внедрить пользовательские утверждения, например роли, внутри токена и где получить jwks (Json Web Key Set), который используется для проверки подписи токена.