RAP Authorization: Implementar Autorizaciones en ABAP Cloud

Kategorie
RAP
Veröffentlicht
Autor
Johannes

Authorization en RAP asegura que los usuarios solo puedan acceder a datos y ejecutar operaciones para las cuales están autorizados. Este artículo muestra los diferentes conceptos de autorización y su implementación.

Conceptos de Autorización en Resumen

AspectoInstance AuthorizationGlobal Authorization
AlcanceInstancias individualesToda la entidad
VerificaciónPor registroUna vez por operación
Caso de uso”¿Puede el usuario editar este viaje?""¿Puede el usuario crear viajes?”
RendimientoMás costoso (por instancia)Más eficiente (una vez)

Instance Authorization

Instance Authorization verifica autorizaciones a nivel de registros individuales. Esto es importante cuando diferentes instancias tienen diferentes requisitos de autorización.

Behavior Definition

managed implementation in class zbp_i_travel unique;
strict ( 2 );
define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance )
{
create;
update;
delete;
action cancel result [1] $self;
action accept result [1] $self;
mapping for ztravel
{
TravelUUID = travel_uuid;
TravelID = travel_id;
AgencyID = agency_id;
CustomerID = customer_id;
Status = overall_status;
}
}

Implementación de Instance Authorization

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD get_instance_authorizations.
" Leer datos de instancia
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( AgencyID Status )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
" Verificar objeto de autorización
DATA(is_authorized_update) = abap_false.
DATA(is_authorized_delete) = abap_false.
DATA(is_authorized_cancel) = abap_false.
" Verificar autorización de actualización
IF requested_authorizations-%update = if_abap_behv=>mk-on
OR requested_authorizations-%action-cancel = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '02'. " Modificar
IF sy-subrc = 0.
is_authorized_update = abap_true.
is_authorized_cancel = abap_true.
ENDIF.
ENDIF.
" Verificar autorización de eliminación
IF requested_authorizations-%delete = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '06'. " Eliminar
IF sy-subrc = 0.
is_authorized_delete = abap_true.
ENDIF.
ENDIF.
" Verificación adicional de estado para Action Cancel
IF is_authorized_cancel = abap_true
AND <travel>-Status <> 'O'. " Solo viajes abiertos
is_authorized_cancel = abap_false.
ENDIF.
" Establecer resultado
APPEND VALUE #(
%tky = <travel>-%tky
%update = COND #(
WHEN is_authorized_update = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%delete = COND #(
WHEN is_authorized_delete = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%action-cancel = COND #(
WHEN is_authorized_cancel = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
) TO result.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Valores de Retorno de Authorization

ValorSignificado
if_abap_behv=>auth-allowedOperación permitida
if_abap_behv=>auth-unauthorizedSin autorización

Global Authorization

Global Authorization verifica autorizaciones a nivel de entidad, independientemente de instancias concretas. Ideal para operaciones CREATE o cuando todas las instancias se tratan igual.

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( global )
{
create;
update;
delete;
static action massUpdate;
}

Implementación de Global Authorization

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR Travel RESULT result.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD get_global_authorizations.
" Verificar autorización CREATE
IF requested_authorizations-%create = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '01'. " Crear
DATA(is_create_authorized) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
ENDIF.
" Verificar autorización Static Action
IF requested_authorizations-%action-massUpdate = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '02'.
DATA(is_mass_update_authorized) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
ENDIF.
result = VALUE #(
%create = is_create_authorized
%action-massUpdate = is_mass_update_authorized
).
ENDMETHOD.
ENDCLASS.

Authorization Combinada (Instance + Global)

En la práctica a menudo se necesitan ambos tipos de Authorization:

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance, global )
{
create;
update;
delete;
action cancel result [1] $self;
static action releaseAll;
}

Implementación

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
" Instance Authorization para UPDATE, DELETE, Actions
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.
" Global Authorization para CREATE y Static Actions
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR Travel RESULT result.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD get_instance_authorizations.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( AgencyID )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
" Autorización basada en agencia
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '02'.
DATA(has_change_auth) = COND #( WHEN sy-subrc = 0 THEN abap_true ).
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '06'.
DATA(has_delete_auth) = COND #( WHEN sy-subrc = 0 THEN abap_true ).
APPEND VALUE #(
%tky = <travel>-%tky
%update = COND #(
WHEN has_change_auth = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%delete = COND #(
WHEN has_delete_auth = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%action-cancel = COND #(
WHEN has_change_auth = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
) TO result.
ENDLOOP.
ENDMETHOD.
METHOD get_global_authorizations.
" Autorización CREATE
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '01'.
DATA(create_auth) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
" Autorización Static Action
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '02'.
DATA(release_auth) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
result = VALUE #(
%create = create_auth
%action-releaseAll = release_auth
).
ENDMETHOD.
ENDCLASS.

Authorization Master y Dependent

En composiciones con relaciones Parent-Child, la autorización puede delegarse desde el Parent.

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance )
{
create;
update;
delete;
association _Booking { create; }
}
define behavior for ZI_Booking alias Booking
persistent table zbooking
lock dependent by _Travel
authorization dependent by _Travel
{
update;
delete;
field ( readonly ) TravelUUID;
association _Travel;
}

Explicación

  • authorization master: Esta entidad realiza la verificación de autorización
  • authorization dependent by _Travel: Booking hereda la autorización de Travel
  • En operaciones sobre Booking se verifica automáticamente la Authorization de Travel

Ventaja

No se necesita implementación de Authorization separada para Booking. La autorización del Parent aplica automáticamente para todas las entidades dependientes.

Precheck para Verificación Temprana de Autorización

Con Precheck se pueden verificar autorizaciones antes de que se ejecute la operación real. Esto es más eficiente ya que las solicitudes erróneas se rechazan temprano.

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance )
{
create ( precheck );
update ( precheck );
delete ( precheck );
action ( precheck ) cancel result [1] $self;
}

Implementación con Precheck

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS precheck_create FOR PRECHECK
IMPORTING entities FOR CREATE Travel.
METHODS precheck_update FOR PRECHECK
IMPORTING entities FOR UPDATE Travel.
METHODS precheck_cancel FOR PRECHECK
IMPORTING keys FOR ACTION Travel~cancel.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD precheck_create.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<entity>).
" Verificar autorización para nueva agencia
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <entity>-AgencyID
ID 'ACTVT' FIELD '01'.
IF sy-subrc <> 0.
APPEND VALUE #(
%cid = <entity>-%cid
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = |Sin autorización para agencia { <entity>-AgencyID }|
)
) TO reported-travel.
APPEND VALUE #( %cid = <entity>-%cid ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD precheck_update.
" Leer datos actuales
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( AgencyID Status )
WITH CORRESPONDING #( entities )
RESULT DATA(travels).
LOOP AT entities ASSIGNING FIELD-SYMBOL(<entity>).
READ TABLE travels INTO DATA(travel)
WITH KEY TravelUUID = <entity>-TravelUUID.
" Los viajes bloqueados no pueden editarse
IF travel-Status = 'L'. " Locked
APPEND VALUE #(
%tky = <entity>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Los viajes bloqueados no pueden editarse'
)
) TO reported-travel.
APPEND VALUE #( %tky = <entity>-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD precheck_cancel.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( Status )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
" Solo los viajes abiertos pueden cancelarse
IF <travel>-Status <> 'O'.
APPEND VALUE #(
%tky = <travel>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Solo los viajes abiertos pueden cancelarse'
)
) TO reported-travel.
APPEND VALUE #( %tky = <travel>-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Interacción con Feature Control

Authorization y Feature Control se complementan:

AspectoAuthorizationFeature Control
PropósitoVerificar autorizaciónControlar elementos UI
ResultadoAllowed/UnauthorizedEnabled/Disabled
MomentoEn ejecuciónAl cargar la UI

Mejor Práctica: Verificación Consistente

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
" Feature Control
METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR Travel RESULT result.
" Authorization
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.
" Método auxiliar común
METHODS check_cancel_allowed
IMPORTING travel TYPE zi_travel
RETURNING VALUE(result) TYPE abap_boolean.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD check_cancel_allowed.
" Lógica central para Feature Control Y Authorization
result = abap_false.
" Solo viajes abiertos
IF travel-Status <> 'O'.
RETURN.
ENDIF.
" Verificación de autorización
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD travel-AgencyID
ID 'ACTVT' FIELD '02'.
IF sy-subrc = 0.
result = abap_true.
ENDIF.
ENDMETHOD.
METHOD get_instance_features.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
DATA(can_cancel) = check_cancel_allowed( <travel> ).
APPEND VALUE #(
%tky = <travel>-%tky
%action-cancel = COND #(
WHEN can_cancel = abap_true
THEN if_abap_behv=>fc-o-enabled
ELSE if_abap_behv=>fc-o-disabled )
) TO result.
ENDLOOP.
ENDMETHOD.
METHOD get_instance_authorizations.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
DATA(can_cancel) = check_cancel_allowed( <travel> ).
APPEND VALUE #(
%tky = <travel>-%tky
%action-cancel = COND #(
WHEN can_cancel = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
) TO result.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Objetos de Autorización en ABAP Cloud

En ABAP Cloud los objetos de autorización se crean con ADT:

  1. Package para Authorization crear
  2. Authorization Object crear (la transacción SU21 no existe)
  3. Authorization Fields definir
  4. En código verificar con AUTHORITY-CHECK OBJECT

Ejemplo de Objeto de Autorización

Authorization Object: ZTRAVEL
Fields:
- ZAGENCY (ID de Agencia)
- ZREGION (Código de Región)
- ACTVT (Actividad: 01=Crear, 02=Modificar, 03=Visualizar, 06=Eliminar)

Mejores Prácticas

  1. Global para CREATE: Operaciones CREATE siempre con Global Authorization, ya que aún no existe instancia.

  2. Instance para UPDATE/DELETE: Cuando las autorizaciones dependen de datos de instancia (p.ej., agencia, región).

  3. Dependent para Composiciones: Entidades hijas heredan autorización del Parent.

  4. Feature Control sincronizado: Botones desactivados también deberían estar unauthorized.

  5. Usar Precheck: Para validación temprana y mejores mensajes de error.

  6. Extraer métodos auxiliares: Lógica de verificación común en métodos reutilizables.

  7. DUMMY para verificaciones genéricas: ID 'ZAGENCY' DUMMY cuando el valor concreto no importa.

Temas Relacionados