我正在使用spring Security和cognito进行身份验证和授权。我通过aws IAM输入了一些自定义角色,我想知道是否有一种方法可以授予对资源的受控访问权限。在网络上,我发现一些将cognito:groups设置为角色并使用了它,但他们使用了过时的类和方法。在最新版本中有没有办法做到这一点?
我尝试创建一个类:
package com.projectname.name.Configurations;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CognitoAccessTokenConverter implements Converter<Jwt, AbstractAuthenticationToken> {
private final JwtGrantedAuthoritiesConverter defaultGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
public CognitoAccessTokenConverter() {
}
@Override
public AbstractAuthenticationToken convert(@NonNull 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("cognito:groups");
//System.out.println("\n!!!!!!!!" +userRoles +"!!!!!!!!!!\n"); DEBUG
if (userRoles != null)
return userRoles
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toSet());
return Collections.emptySet();
}
}
/*
import java.util.Map;
import java.util.Set;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
import org.springframework.stereotype.Component;
import org.springframework.
@Component
public class CognitoAccessTokenConverter extends OAuth2AuthorizationCodeRequestAuthenticationToken{
private static final String COGNITO_GROUPS = "cognito:groups";
private static final String SPRING_AUTHORITIES = "authorities";
private static final String COGNITO_USERNAME = "username";
private static final String SPRING_USER_NAME = "user_name";
}
@Component
public class CognitoAccessTokenConverter extends {
// Note: This the core part.
private static final String COGNITO_GROUPS = "cognito:groups";
private static final String SPRING_AUTHORITIES = "authorities";
private static final String COGNITO_USERNAME = "username";
private static final String SPRING_USER_NAME = "user_name";
@SuppressWarnings("unchecked")
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
if (claims.containsKey(COGNITO_GROUPS))
((Map<String, Object>) claims).put(SPRING_AUTHORITIES, claims.get(COGNITO_GROUPS));
if (claims.containsKey(COGNITO_USERNAME))
((Map<String, Object>) claims).put(SPRING_USER_NAME, claims.get(COGNITO_USERNAME));
return super.extractAuthentication(claims);
}
} */
如何在我Spring Security配置中使用此转换?
package com.SSDProject.Booked.Configurations;
import java.io.*;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.client.endpoint.DefaultRefreshTokenTokenResponseClient;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/admin").hasAuthority("max")
.requestMatchers("/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login();
return http.build();
}
帮帮我,我试着实现它,到处寻找。有帮助吗?你有主意吗?
2条答案
按热度按时间epggiuax1#
我最近使用SpringBoot 2.x和Java 17创建了相同的PoC。在我的情况下,我的IDE没有任何弃用警告,下面是我的示例:
你的代码中哪一行被弃用了?你使用的是什么版本的resource-server?对我来说,spring-boot-starter-oauth2-resource-server是2.7.5。
这实际上不是一个答案,但我没有对这个问题发表评论的名声:)
vyu0f0g12#
您的Spring应用程序是服务器端呈现的UI(Thymeleaf、JSF等)还是REST API(
@RestController
或@Controller
与@ResponseBody
)?在第二种情况下,您的应用是资源服务器。OAuth2登录应由客户端而不是资源服务器处理:客户端获取访问令牌,并将其作为Authorization头发送给资源服务器。
在我对Use Keycloak Spring Adapter with Spring Boot 3的回答中,我解释了如何配置Spring资源服务器和客户端,您需要为Cognito做的调整是issuer URI和私有声明名称,以便从中提取授权。
使用my starters(
spring-boot-starter-oauth2-resource-server
周围的薄 Package 器)配置具有从cognito:groups
Map的权限的资源服务器可以像下面这样简单:如果您的应用程序只是一个客户端,那么我的启动器将不会有任何帮助。
如果您的应用既是资源服务器又是客户端(提供JSON有效负载和服务器端呈现的UI,例如Thymeleaf),那么您必须定义第二个
SecurityFilterChain
bean。如果你不想使用我的启动器,那么你必须在前面链接的答案中再写一些java conf.细节。