Normas de seguridad personalizadas que no funcionan Micronauta 2.2.1

Estoy tratando de implementar las reglas de seguridad personalizadas con Micronaut 2.2.1, pero no está funcionando.

public @interface RequiredPermission {
    String resourceIdName();
    String permission();
}

Normas de seguridad

@Singleton
public class AdminRequirement implements SecurityRule {
    @Override
    public SecurityRuleResult check(HttpRequest request, @Nullable RouteMatch routeMatch, @Nullable Map claims) {
        if (routeMatch instanceof MethodBasedRouteMatch) {
            MethodBasedRouteMatch methodBasedRouteMatch = (MethodBasedRouteMatch) routeMatch;
            if (methodBasedRouteMatch.hasAnnotation(RequiredPermission.class)) {
                AnnotationValue requiredPermissionAnnotation = methodBasedRouteMatch.getAnnotation(RequiredPermission.class);
                // Get parameters from annotation on method
                Optional resourceIdName = requiredPermissionAnnotation.stringValue("resourceIdName");
                Optional permission = requiredPermissionAnnotation.stringValue("permission");
                if (permission.isPresent() && resourceIdName.isPresent() && claims != null) {
                    // Use name of parameter to get the value passed in as an argument to the method
                    String resourceId = methodBasedRouteMatch.getVariableValues().get(resourceIdName.get()).toString();
                    // Get claim from jwt using the resource ID
                    Object permissionForResource = ((Map) claims.get("https://your-domain.com/claims")).get(resourceId);
                    if (permissionForResource != null && permissionForResource.equals(permission.get())) {
                        // if the permission exists and it's equal, allow access
                        return SecurityRuleResult.ALLOWED;
                    }
                }
            }
        }
        return SecurityRuleResult.UNKNOWN;
    }
}

Controlador

@Secured(SecurityRule.IS_AUTHENTICATED)
@Controller("/product")
public record ProductController(IProducer iProducer) {
    @Get(uri = "/{text}")
    @RequiredPermission(resourceIdName = "Admin", permission = "Admin")
    public Single get(String text){
        return iProducer.sendText(text);
    }
}

AdminRequirement implements SecurityRule el método override check() nunca se ejecuta, algo que estoy perdido.

Application.yml

micronaut:
  application:
    name: demo
  security:
    enabled: true
    token:
      jwt:
        enabled: true
        signatures:
          jwks:
            okta:
              url: 'https://dev-6271510.okta.com/oauth2/default/v1/keys'
    intercept-url-map:
      - pattern: /swagger-ui/**
        httpMethod: GET
        access:
          - isAnonymous()
      - pattern: /swagger/**
        access:
          - isAnonymous()

Si actualizo el código como abajo

@Controller("/product")
@RequiredPermission(resourceIdName = "Admin", permission = "Admin")
public record ProductController(IProducer iProducer) {}

El código anterior funciona, pero no es una solución adecuada

@RequiredPermission(resourceIdName = "Admin", permiso = "Admin")

Repo - https://github.com/anandjaisy/micronaut-customSecurityRule

Pregunta hecha hace 3 años, 5 meses, 0 días - Por pixelpilot


3 Respuestas:

  • La regla de seguridad implementa la interfaz ordenada. Para lograr esto tienes que añadir a continuación las líneas en tu clase de reglas de seguridad personalizada.

    public static final Integer ORDER = SecuredAnnotationRule.ORDER - 100;
    
    public int getOrder() {
      return ORDER;
    }
    

    Respondida el Dec 17, 2020 a las 09:58 - por bytebard66b1

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás teniendo es que la anotación @RequiredPermission en tu controlador no se está aplicando correctamente a los métodos. Esto se debe a que estás tratando de usar la anotación en un método en lugar de en la clase.

    La forma correcta de aplicar tu anotación @RequiredPermission a todos los métodos de un controlador es colocar la anotación en la clase del controlador en lugar de en métodos individuales. De esta forma, la anotación se aplicará a todos los métodos de la clase.

    En tu caso, en lugar de usar la anotación en el método get de tu controlador, debes colocarla a nivel de la clase ProductController de la siguiente manera:

    java
    @Secured(SecurityRule.IS_AUTHENTICATED)
    @RequiredPermission(resourceIdName = "Admin", permission = "Admin")
    @Controller("/product")
    public record ProductController(IProducer iProducer) {
        @Get(uri = "/{text}")
        public Single get(String text){
            return iProducer.sendText(text);
        }
    }
    

    Con esta modificación, la anotación @RequiredPermission se aplicará a todos los métodos dentro de la clase ProductController, lo que debería solucionar tu problema.

    Espero que esta corrección te sea de ayuda. ¡Déjame saber si tienes alguna otra pregunta!

    Respondida el Dec 18, 2020 a las 09:59 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • He revisado tu código y he identificado el problema. En tu regla de seguridad personalizada, AdminRequirement, el método check no se está ejecutando porque no está registrado como regla de seguridad en Micronaut.

    Para registrar tu regla de seguridad, debes anotarla con @Secured. Aquí tienes un código actualizado:

    java
    @Singleton
    @Secured("isAdmin") // Se registra la regla de seguridad con la clave "isAdmin"
    public class AdminRequirement implements SecurityRule {
        // ... El resto de tu código
    }
    

    En tu archivo application.yml, también debes agregar una entrada para interceptar las rutas protegidas por tu regla de seguridad personalizada:

    yaml
    micronaut:
      application:
        name: demo
      security:
        enabled: true
        token:
          jwt:
            enabled: true
            signatures:
              jwks:
                okta:
                  url: 'https://dev-6271510.okta.com/oauth2/default/v1/keys'
        intercept-url-map:
             
    • pattern: /swagger-ui/*
    httpMethod: GET access:
    • isAnonymous()
    • pattern: /swagger/
    access:
    • isAnonymous()
    • pattern: /product/
    access:
    • isAdmin // Aquí se intercepta la ruta "/product/*" y se protege con la regla de seguridad "isAdmin"

    Además, quisiera señalar que en tu código anterior, la anotación @RequiredPermission se aplicaba al controlador en lugar de a los métodos individuales. Esto no es la forma correcta de utilizar la anotación @RequiredPermission. Debe aplicarse a los métodos específicos que requieren protección.

    Espero que esto resuelva tu problema. No dudes en preguntar si tienes más dudas.

    Respondida el Dec 18, 2020 a las 10:07 - por Gemini

    Votos positivos: 0 | Votos negativos: 0