RAP Authorization: Berechtigungen in ABAP Cloud implementieren

kategorie
RAP
Veröffentlicht
autor
Johannes

Authorization in RAP stellt sicher, dass Benutzer nur auf Daten zugreifen und Operationen ausführen können, für die sie berechtigt sind. Dieser Artikel zeigt die verschiedenen Autorisierungskonzepte und deren Implementierung.

Authorization-Konzepte im Überblick

AspektInstance AuthorizationGlobal Authorization
ScopeEinzelne InstanzenGesamte Entität
PrüfungPro DatensatzEinmalig pro Operation
Anwendungsfall”Darf User diese Reise bearbeiten?""Darf User überhaupt Reisen erstellen?”
PerformanceAufwändiger (pro Instanz)Effizienter (einmalig)

Instance Authorization

Instance Authorization prüft Berechtigungen auf Ebene einzelner Datensätze. Dies ist wichtig, wenn unterschiedliche Instanzen unterschiedliche Berechtigungsanforderungen haben.

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;
}
}

Implementation der 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.
" Instanzdaten lesen
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>).
" Berechtigungsobjekt prüfen
DATA(is_authorized_update) = abap_false.
DATA(is_authorized_delete) = abap_false.
DATA(is_authorized_cancel) = abap_false.
" Update-Berechtigung prüfen
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'. " Ändern
IF sy-subrc = 0.
is_authorized_update = abap_true.
is_authorized_cancel = abap_true.
ENDIF.
ENDIF.
" Delete-Berechtigung prüfen
IF requested_authorizations-%delete = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '06'. " Löschen
IF sy-subrc = 0.
is_authorized_delete = abap_true.
ENDIF.
ENDIF.
" Zusätzliche Status-Prüfung für Cancel-Action
IF is_authorized_cancel = abap_true
AND <travel>-Status <> 'O'. " Nur offene Reisen
is_authorized_cancel = abap_false.
ENDIF.
" Ergebnis setzen
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.

Rückgabewerte der Authorization

WertBedeutung
if_abap_behv=>auth-allowedOperation erlaubt
if_abap_behv=>auth-unauthorizedKeine Berechtigung

Global Authorization

Global Authorization prüft Berechtigungen auf Entitätsebene, unabhängig von konkreten Instanzen. Ideal für CREATE-Operationen oder wenn alle Instanzen gleich behandelt werden.

Behavior Definition

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

Implementation der 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.
" CREATE-Berechtigung prüfen
IF requested_authorizations-%create = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '01'. " Anlegen
DATA(is_create_authorized) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
ENDIF.
" Static Action Berechtigung prüfen
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.

Kombinierte Authorization (Instance + Global)

In der Praxis benötigt man oft beide Arten von 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;
}

Implementation

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
" Instance Authorization für UPDATE, DELETE, Actions
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.
" Global Authorization für CREATE und 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>).
" Agentur-basierte Berechtigung
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.
" CREATE-Berechtigung
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 ).
" Static Action Berechtigung
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 und Dependent

Bei Kompositionen mit Parent-Child-Beziehungen kann die Autorisierung vom Parent delegiert werden.

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;
}

Erklärung

  • authorization master: Diese Entität führt die Berechtigungsprüfung durch
  • authorization dependent by _Travel: Booking erbt die Berechtigung von Travel
  • Bei Operationen auf Booking wird automatisch die Authorization von Travel geprüft

Vorteil

Keine separate Authorization-Implementierung für Booking nötig. Die Parent-Berechtigung gilt automatisch für alle abhängigen Entitäten.

Precheck für frühe Berechtigungsprüfung

Mit Precheck können Berechtigungen geprüft werden, bevor die eigentliche Operation ausgeführt wird. Dies ist effizienter, da fehlerhafte Requests früh abgelehnt werden.

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;
}

Implementation mit 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>).
" Berechtigung für neue Agentur prüfen
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 = |Keine Berechtigung für Agentur { <entity>-AgencyID }|
)
) TO reported-travel.
APPEND VALUE #( %cid = <entity>-%cid ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD precheck_update.
" Aktuelle Daten lesen
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.
" Gesperrte Reisen können nicht bearbeitet werden
IF travel-Status = 'L'. " Locked
APPEND VALUE #(
%tky = <entity>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Gesperrte Reisen können nicht bearbeitet werden'
)
) 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>).
" Nur offene Reisen können storniert werden
IF <travel>-Status <> 'O'.
APPEND VALUE #(
%tky = <travel>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Nur offene Reisen können storniert werden'
)
) TO reported-travel.
APPEND VALUE #( %tky = <travel>-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Zusammenspiel mit Feature Control

Authorization und Feature Control ergänzen sich:

AspektAuthorizationFeature Control
ZweckBerechtigung prüfenUI-Elemente steuern
ErgebnisAllowed/UnauthorizedEnabled/Disabled
TimingBei AusführungBeim Laden der UI

Best Practice: Konsistente Prüfung

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.
" Gemeinsame Hilfsmethode
METHODS check_cancel_allowed
IMPORTING travel TYPE zi_travel
RETURNING VALUE(result) TYPE abap_boolean.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD check_cancel_allowed.
" Zentrale Logik für Feature Control UND Authorization
result = abap_false.
" Nur offene Reisen
IF travel-Status <> 'O'.
RETURN.
ENDIF.
" Berechtigungsprüfung
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.

Berechtigungsobjekte in ABAP Cloud

In ABAP Cloud werden Berechtigungsobjekte mit ADT erstellt:

  1. Package für Authorization anlegen
  2. Authorization Object erstellen (Transaktion SU21 gibt es nicht)
  3. Authorization Fields definieren
  4. Im Code mit AUTHORITY-CHECK OBJECT prüfen

Beispiel Berechtigungsobjekt

Authorization Object: ZTRAVEL
Fields:
- ZAGENCY (Agency ID)
- ZREGION (Region Code)
- ACTVT (Activity: 01=Create, 02=Change, 03=Display, 06=Delete)

Best Practices

  1. Global für CREATE: CREATE-Operationen immer mit Global Authorization, da noch keine Instanz existiert.

  2. Instance für UPDATE/DELETE: Wenn Berechtigungen von Instanzdaten abhängen (z.B. Agentur, Region).

  3. Dependent für Kompositionen: Child-Entitäten erben Berechtigung vom Parent.

  4. Feature Control synchron halten: Deaktivierte Buttons sollten auch unauthorized sein.

  5. Precheck nutzen: Für frühe Validierung und bessere Fehlermeldungen.

  6. Hilfsmethoden extrahieren: Gemeinsame Prüflogik in wiederverwendbare Methoden auslagern.

  7. DUMMY für generische Prüfungen: ID 'ZAGENCY' DUMMY wenn der konkrete Wert egal ist.

Weiterführende Themen