Spring Security 我用的是Cognito + Spring安全系统,有没有授权的方法?

nwwlzxa7  于 2023-01-13  发布在  Spring
关注(0)|答案(2)|浏览(137)

我正在使用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();
    }

帮帮我,我试着实现它,到处寻找。有帮助吗?你有主意吗?

epggiuax

epggiuax1#

我最近使用SpringBoot 2.x和Java 17创建了相同的PoC。在我的情况下,我的IDE没有任何弃用警告,下面是我的示例:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.csrf()
            .and()
            .requestMatchers().antMatchers("/api/**")
            .and()
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .userDetailsService(null)
            .oauth2ResourceServer(oauth2 ->
                    oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(grantedAuthoritiesExtractor())));

    return http.build();
}

private JwtAuthenticationConverter grantedAuthoritiesExtractor() {
    JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
    jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwt -> {
                String[] scopes;
                if (jwt.getClaims().containsKey("cognito:groups")) {
                    scopes = ((JSONArray) jwt.getClaims().get("cognito:groups")).toArray(new String[0]);
                } else {
                    scopes = ((String) jwt.getClaims().getOrDefault("scope", "")).split(" ");
                }
                return Arrays.stream(scopes)
                        .map(role -> new SimpleGrantedAuthority("ROLE_" + role.toUpperCase(Locale.ROOT)))
                        .collect(Collectors.toSet());
            }

    );

    return jwtAuthenticationConverter;
}

你的代码中哪一行被弃用了?你使用的是什么版本的resource-server?对我来说,spring-boot-starter-oauth2-resource-server是2.7.5。
这实际上不是一个答案,但我没有对这个问题发表评论的名声:)

vyu0f0g1

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 startersspring-boot-starter-oauth2-resource-server周围的薄 Package 器)配置具有从cognito:groupsMap的权限的资源服务器可以像下面这样简单:

<dependency>
    <groupId>com.c4-soft.springaddons</groupId>
    <artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
    <version>6.0.10</version>
</dependency>
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
}
com.c4-soft.springaddons.security.issuers[0].location=https://cognito-idp.Region.amazonaws.com/your user pool ID/.well-known/openid-configuration
com.c4-soft.springaddons.security.issuers[0].authorities.claims=cognito:groups

# This is probably too permissive but can be fine tuned (origins, headers and methods can be defined per path)
com.c4-soft.springaddons.security.cors[0].path=/**

如果您的应用程序只是一个客户端,那么我的启动器将不会有任何帮助。
如果您的应用既是资源服务器又是客户端(提供JSON有效负载和服务器端呈现的UI,例如Thymeleaf),那么您必须定义第二个SecurityFilterChain bean。
如果你不想使用我的启动器,那么你必须在前面链接的答案中再写一些java conf.细节。

相关问题