java 无法授权ReflectiveMethodInvocation决策ExpressionAuthorizationDecision [granted=false,expressionAttribute=hasAuthority('ROLE_PROF')]

mnemlml8  于 2023-06-28  发布在  Java
关注(0)|答案(1)|浏览(152)

我想将基于角色的身份验证添加到我的get user API中,但我的实现是-SecurityConfigs.java

public class SecurityConfig {

    private final JwtAuthConverter jwtAuthConverter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf()
                .disable()
                .authorizeHttpRequests()
                .anyRequest().permitAll();
        http
                .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(jwtAuthConverter);
        http
                .sessionManagement()
                .sessionCreationPolicy(STATELESS);

        return http.build();
    }

和JwtAuthConvert类:

private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter =
            new JwtGrantedAuthoritiesConverter();

    @Value("${jwt.auth.converter.principle-attribute}")
    private String principleAttribute;
    @Value("${jwt.auth.converter.resource-id}")
    private String resourceId;

    @Override
    public AbstractAuthenticationToken convert(@NonNull Jwt jwt) {
        Collection<GrantedAuthority> authorities = Stream.concat(
                jwtGrantedAuthoritiesConverter.convert(jwt).stream(),
                extractResourceRoles(jwt).stream()
        ).collect(Collectors.toSet());

        return new JwtAuthenticationToken(
                jwt,
                authorities,
                getPrincipleClaimName(jwt)
        );
    }

    private String getPrincipleClaimName(Jwt jwt) {
        String claimName = JwtClaimNames.SUB;
        if (principleAttribute != null) {
            claimName = principleAttribute;
        }
        return jwt.getClaim(claimName);
    }

    private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt) {
        Map<String, Object> resourceAccess;
        Map<String, Object> resource;
        Collection<String> resourceRoles;
        if (jwt.getClaim("resource_access") == null) {
            return Set.of();
        }
        resourceAccess = jwt.getClaim("resource_access");

        if (resourceAccess.get(resourceId) == null) {
            return Set.of();
        }
        resource = (Map<String, Object>) resourceAccess.get(resourceId);

        resourceRoles = (Collection<String>) resource.get("roles");
        return resourceRoles
                .stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toSet());
    }

获取用户API

@GetMapping(path = "/{userName}")
    @PreAuthorize("hasRole('PROF')")
    public List<UserRepresentation> getUser(@PathVariable("userName") String userName){
        List<UserRepresentation> user = userservice.getUser(userName);
        return user;
    }

问题:当我尝试使用PROF角色使用Get API时,我得到Status Code 403 Forbidden错误,尽管我允许PROF角色执行此操作。我得到以下日志

2023-06-23T11:26:54.564+01:00 DEBUG 7428 --- [nio-8090-exec-3] .s.r.w.a.BearerTokenAuthenticationFilter : Set SecurityContextHolder to JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@b3eb5836, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[SCOPE_email, SCOPE_profile]]
2023-06-23T11:26:54.565+01:00 DEBUG 7428 --- [nio-8090-exec-3] o.s.security.web.FilterChainProxy        : Secured GET /user/nouhaila
2023-06-23T11:26:54.571+01:00 DEBUG 7428 --- [nio-8090-exec-3] horizationManagerBeforeMethodInterceptor : Authorizing method invocation ReflectiveMethodInvocation: public java.util.List com.codetech.authserver.controller.UserController.getUser(java.lang.String); target is of class [com.codetech.authserver.controller.UserController]
2023-06-23T11:26:54.609+01:00 DEBUG 7428 --- [nio-8090-exec-3] horizationManagerBeforeMethodInterceptor : Failed to authorize ReflectiveMethodInvocation: public java.util.List com.codetech.authserver.controller.UserController.getUser(java.lang.String); target is of class [com.codetech.authserver.controller.UserController] with authorization manager org.springframework.security.config.annotation.method.configuration.DeferringObservationAuthorizationManager@7fdea099 and decision ExpressionAuthorizationDecision [granted=false, expressionAttribute=hasAuthority('ROLE_PROF')]
bttbmeg0

bttbmeg01#

您的SecurityConfig可能没有示例化(缺少@Configuration装饰器?)。在securityFilterChain@Bean定义中设置一个断点,以检查您的自定义SecurityFilterChain bean是否已示例化。
除此之外,使用以下代码可能会更简单/更安全

resourceRoles = jwt.getClaims()
    .getOrDefault("resource_access", Map.of())
    .getOrDefault(resourceId, Map.of())
    .getOrDefault("roles", List.of()); // you forgot to check for null roles

...
或者使用"my" starters,它已经完成了这种检查,并且支持从多个声明中检索角色(realm_access.roles和一个或多个resource_access.{clientId}.roles

相关问题