我建议使用jwt 令牌 https://jwt.io/,它作为“授权”标头附加到后端的每个请求。该令牌由三部分组成,其中一部分保存有关用户的数据,另一部分保存签名,因此您可以验证您的令牌是否由可信来源创建。数据部分可能看起来像这样:
{
"iss": "Online JWT Builder",
"iat": 1580283510,
"exp": 1611819510,
"aud": "www.example.com",
"sub": "[email protected] /cdn-cgi/l/email-protection",
"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>
现在您可以启用安全性并使用配置类对其进行配置。在里面,您可以定义请求必须具有的范围、如何签署令牌以及路由应该是公开的还是安全的。
@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、to Jwt Converter 中的角色和@EnableGlobalMethodSecurity
注释使您能够安全即使在方法级别 https://www.baeldung.com/spring-security-method-security.
@Transactional
@PreAuthorize("hasRole('ROLE_PROJECT_MANAGER')")
public Page<Project> findAll(Pageable pageable) {
return projectRepository.findAll(pageable);
}
Azure Active Directory 应该支持智威汤逊 https://azure.microsoft.com/de-de/blog/windows-azure-active-directory-supports-json-web-tokens/,但我没有这个 IDP 的经验。
我无法回答的是,如何在令牌内注入自定义声明(例如角色)以及从哪里获取用于验证令牌签名的 jwks(Json Web 密钥集)。