我正在尝试根据我在声明中获得的角色来验证自己的身份。基本上,只有当特定角色是声明的一部分时,我才希望能够连接到我的应用程序
依赖关系:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.1.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
<version>3.1.4</version>
<scope>compile</scope>
</dependency>
这是我的安全课程:
@Configuration
@EnableWebSecurity(debug = true)
@AllArgsConstructor
public class SecurityOAuth2Config {
private static final Logger LOGGER = LogManager.getLogger(SecurityOAuth2Config.class);
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(AbstractHttpConfigurer::disable)
.headers(header -> header.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(req -> req
.requestMatchers(antMatcher("/actuator/health")).permitAll()
.requestMatchers(antMatcher("/actuator/info")).permitAll()
.requestMatchers(antMatcher("/h2-console/**")).permitAll()
// Invoked internally inside the kubernetes cluster
.requestMatchers(antMatcher("/internal/api/**")).permitAll()
.requestMatchers(antMatcher("/api/**"))
.hasAnyRole("User1", "Admin3","TestDataUploader")
.anyRequest().permitAll()
)
.oauth2ResourceServer((oauth2) -> oauth2.jwt(jwtConfigurer ->
jwtConfigurer.jwtAuthenticationConverter(jwtAuthenticationConverter())));
return http.getOrBuild();
}
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
var grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
grantedAuthoritiesConverter.setAuthoritiesClaimName("role");
grantedAuthoritiesConverter.setAuthorityPrefix("");
var jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
@Bean
public GrantedAuthoritiesMapper userAuthoritiesMapper() {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
LOGGER.info("AUTHORITIES " + authorities);
authorities.forEach(authority -> {
if (authority instanceof OidcUserAuthority oidcAuth) {
oidcAuth.getUserInfo().getClaimAsStringList("role").forEach(
role -> mappedAuthorities.add(new SimpleGrantedAuthority("" + role)));
}
});
mappedAuthorities.addAll(authorities);
return mappedAuthorities;
};
}
}
我总是未经授权
不记名令牌示例
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1699881658,
"iss": "https://id.test.io/",
"upn": "Jon",
"role": [
"Admin",
"Approve"
]
}
控制器端点示例
@RestController
@RequestMapping("/api")
@AllArgsConstructor
public class ApplicationListController {
private ServiceApp serviceApp;
@GetMapping("/app")
public Collection<Response> getApplications() {
return serviceApp.loadResponse();
}
}
您应该删除您的
GrantedAuthoritiesMapper
bean,它会重复您在 JwtAuthenticationConverter
上配置的内容。
使用
.hasAnyRole("User1", "Admin3","TestDataUploader")
时,您希望身份验证包含 ROLE_User1
、ROLE_Admin3
或 ROLE_TestDataUploader
权限之一,但映射不带前缀的 "role": [ "Admin", "Approve" ]
声明 => 权限是 Admin
和 Approve
=> 不匹配,因为缺少 ROLE_
前缀并且预期角色是 Admin3
(不是您声明中包含的 Admin
)。两种选择
.hasAnyAuthority("User1", "Admin","TestDataUploader")
.hasAnyRole("User1", "Admin","TestDataUploader")
并将您的 JwtAuthenticationConverter
更新为 grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
尝试使用以下配置:
@Configuration
@EnableWebSecurity(debug = true)
@AllArgsConstructor
public class SecurityOAuth2Config {
private static final Logger LOGGER = LogManager.getLogger(SecurityOAuth2Config.class);
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtAuthenticationConverter jwtAuthenticationConverter) throws Exception {
http
.cors(AbstractHttpConfigurer::disable)
.headers(header -> header.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(req -> req
.requestMatchers(antMatcher("/actuator/health")).permitAll()
.requestMatchers(antMatcher("/actuator/info")).permitAll()
.requestMatchers(antMatcher("/h2-console/**")).permitAll()
// Invoked internally inside the kubernetes cluster
.requestMatchers(antMatcher("/internal/api/**")).permitAll()
.requestMatchers(antMatcher("/api/**"))
.hasAnyRole("Admin", "User1", "TestDataUploader")
.anyRequest().permitAll()
)
.oauth2ResourceServer((oauth2) -> oauth2.jwt(jwtConfigurer ->
jwtConfigurer.jwtAuthenticationConverter(jwtAuthenticationConverter)));
return http.getOrBuild();
}
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
var grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
grantedAuthoritiesConverter.setAuthoritiesClaimName("role");
grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
var jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
}
您也可以考虑使用我的入门工具:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-starter-oidc</artifactId>
<version>7.1.13</version>
</dependency>
com:
c4-soft:
springaddons:
oidc:
ops:
# Change this to point to your own authorization server
- iss: https://localhost:8443/realms/master
username-claim: upn
authorities:
- path: $.roles
prefix: ROLE_
resourceserver:
permit-all:
- /actuator/health
- /actuator/info
- /h2-console/**
- /internal/api/**
cors:
@Configuration
@EnableWebSecurity(debug = true)
@EnableMethodSecurity
@AllArgsConstructor
public class SecurityOAuth2Config {
}
@RestController
@RequestMapping("/api")
@AllArgsConstructor
public class ApplicationListController {
private ServiceApp serviceApp;
@GetMapping("/app")
@PreAuthorize("hasAnyRole('Admin', 'User1', 'TestDataUploader')")
public Collection<Response> getApplications() {
return serviceApp.loadResponse();
}
}