oauth2.0 接收到“范围不足”错误,即使我有足够的范围

ttcibm8c  于 2023-05-16  发布在  其他
关注(0)|答案(1)|浏览(118)

使用OAuth2 ResourceServer通过JWT令牌实现身份验证(Spring 3)

spring安全配置

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
public class SpringSecurityConfig {
    private final AuthenticationService authenticationService;
    private final PasswordEncoder passwordEncoder;
    private final RsaProperties rsaKeys;

    @Bean
    public AuthenticationManager authManager() {
        var authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(authenticationService);
        authProvider.setPasswordEncoder(passwordEncoder);
        return new ProviderManager(authProvider);
    }

    @Bean
    public JwtEncoder jwtEncoder() {
        JWK jwk = new RSAKey.Builder(rsaKeys.publicKey()).privateKey(rsaKeys.privateKey()).build();
        JWKSource<SecurityContext> jwkSource = new ImmutableJWKSet<>(new JWKSet(jwk));
        return new NimbusJwtEncoder(jwkSource);
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withPublicKey(rsaKeys.publicKey()).build();
    }

    @Bean
    public JwtTokenService tokenService() {
        return new JwtTokenService(jwtEncoder());
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                .csrf().disable()
                .authorizeHttpRequests()
                .requestMatchers("/authentication/login").permitAll()
                .requestMatchers("/credit/request").hasAuthority("SCOPE_usr")
                .and()
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer :: jwt )
                .build();
    }
}

JwtTokenService

@Component
@RequiredArgsConstructor
public class JwtTokenService {
    private final JwtEncoder jwtEncoder;

    public String generateAccessToken(UserDetailsEntity userDetails) {
        Instant now = Instant.now();
        String scope = userDetails.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.joining(" "));

        JwtClaimsSet claims = JwtClaimsSet.builder()
                .issuer("self")
                .issuedAt(now)
                .expiresAt(now.plus(2, ChronoUnit.HOURS))
                .subject(userDetails.getUsername())
                .claim("scope", scope)
                .build();
        return this.jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
    }

    public String generateRefreshToken(UserDetailsEntity userDetails) {
        Instant now = Instant.now();
        String scope = userDetails.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.joining(" "));

        JwtClaimsSet claims = JwtClaimsSet.builder()
                .issuer("self")
                .issuedAt(now)
                .expiresAt(now.plus(10, ChronoUnit.HOURS))
                .subject(userDetails.getUsername())
                .claim("scope", scope)
                .build();
        return this.jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
    }

    public String parseToken(String token) {
        try {
            SignedJWT decodedJwt = SignedJWT.parse(token);
            return decodedJwt.getJWTClaimsSet().getSubject();
        } catch (ParseException e) {
            System.out.println(e.getStackTrace());
        }
        return null;
    }
}

因此,我的令牌包含声明“scope”,值为“SCOPE_usr”,这是“/credit/request”端点所需的,即使服务器继续响应403代码错误和“范围不足”消息。我尝试在JwtTokenService中将作用域硬编码为“SCOPE_usr”,这样我所有的令牌都通过了端点检查(我明白,这听起来可能很愚蠢,但目前我认为OAuth2服务器就是这样工作的)。有人能解释一下,OAuth2 ResourceServer检查作用域的方式是什么,我应该怎么解决这个问题?

kr98yfug

kr98yfug1#

您使用的是默认的权限转换器,它接受范围声明条目并为其添加SCOPE_前缀。使用此转换器和您在conf中的requestMatchers访问规则,令牌中的范围应该是usr(将转换为SCOPE_usr权限)。

相关问题