Es gibt einen schönen Hinweis 2565111 der das Problem betrifft, dass keine Passwort zurücksetzen Funktion auf dem Fiori Launchpad angeboten wird. Klingt sehr vielversprechend weil genau die Frage nämlich immer öfter kam. Dachte ich… im Hinweis steht nämlich drin:
“Kannst du gerne selbst umsetzen wenn du es brauchst” 🙂
Als Erstes die einfachen Dinge nämlich ein oData-Service für die Abwicklung im Backend, bzw. das wirkliche Zurücksetzen und neu generieren des Passwortes.
Der Entitätstyp des oData-Services ist sehr simpel.
Über die SAPUI5-Anwendung sollen später E-Mailadresse und Benutzernamen zum Abgleich mitgegeben werden.
Die Implementierung der create_entityset sieht dann folgendermaßen aus:
DATA lv_zeichen TYPE char80.
DATA ls_data TYPE zfiori_rpw_s.
DATA lt_mail_body TYPE soli_tab.
DATA lv_password TYPE char20.
DATA lt_return TYPE TABLE OF bapiret2.
DATA ls_address TYPE bapiaddr3.
io_data_provider->read_entry_data(
IMPORTING
es_data = ls_data
).
"Sicherheitsprüfung - Mailadresse muss im Benutzerstamm gepflegt sein
CALL FUNCTION 'BAPI_USER_GET_DETAIL'
EXPORTING
username = ls_data-uname
IMPORTING
address = ls_address
TABLES
return = lt_return.
IF to_lower( ls_data-mail ) NE to_lower( ls_address-e_mail ). "Mailadresse falsch!!!
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING
textid = /iwbep/cx_mgw_busi_exception=>business_error
message = |Mailadressen Benutzerstammsatz und Request stimmen nicht überein|.
ENDIF.
"Neues Passwort generieren
CONCATENATE
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'abcdefghijklmnopqrstuvwxyz'
'123456789@$%&/\()=+-#~[]{}'
INTO lv_zeichen.
CALL FUNCTION 'RSEC_GENERATE_PASSWORD'
EXPORTING
alphabet = lv_zeichen
alphabet_length = 0
force_init = ' '
output_length = 20
downwards_compatible = ' '
IMPORTING
output = lv_password
EXCEPTIONS
some_error = 1.
"Ändere User PW
CALL FUNCTION 'BAPI_USER_CHANGE'
EXPORTING
username = ls_data-uname
password = CONV bapipwd( lv_password )
passwordx = 'X'
TABLES
return = lt_return.
"Prüfe, ob User Change fehlerfrei erfolgt ist
IF line_exists( lt_return[ type = 'E' ] ) OR line_exists( lt_return[ type = 'A' ] ).
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING
textid = /iwbep/cx_mgw_busi_exception=>business_error
message = |Fehler bei BAPI_USER_CHANGE|.
ENDIF.
"Entsperre Benutzer
CLEAR lt_return.
CALL FUNCTION 'BAPI_USER_UNLOCK'
EXPORTING
username = ls_data-uname
TABLES
return = lt_return.
"Prüfe, ob User Unlock fehlerfrei erfolgt ist
IF line_exists( lt_return[ type = 'E' ] ) OR line_exists( lt_return[ type = 'A' ] ).
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING
textid = /iwbep/cx_mgw_busi_exception=>business_error
message = |Fehler bei BAPI_USER_UNLOCK|.
ENDIF.
"Mailversand
DATA(lo_bcs_message) = NEW cl_bcs_message( ).
lo_bcs_message->add_recipient(
EXPORTING
iv_address = CONV #( ls_data-mail )
).
lo_bcs_message->set_send_immediately( iv_immediately = abap_true ). "Soll sofort gesendet werden
"Senderadresse aus Stammsatz des Servicebenutzers
CALL FUNCTION 'BAPI_USER_GET_DETAIL'
EXPORTING
username = sy-uname
IMPORTING
address = ls_address
TABLES
return = lt_return.
lo_bcs_message->set_sender(
EXPORTING
iv_address = COND #( WHEN ls_address-e_mail IS NOT INITIAL THEN to_lower( ls_address-e_mail ) ELSE 'no-reply.fiori@dummy.de' )
).
lo_bcs_message->set_subject( |Zurücksetzung des Kennworts| ).
lt_mail_body = VALUE #(
( line = |<p>Guten Tag,| )
( line = |<p>Sie haben ihr Kennwort vergessen?<br>| )
( line = |<p>Ihr neues Kennwort lautet: { lv_password }</p>| )
( line = |<p>Mit freundlichen Grüßen<br></p>| )
).
DATA(lt_mail_body_solix) = cl_bcs_convert=>soli_to_solix( it_soli = lt_mail_body ).
DATA(l_content_bin) = cl_bcs_convert=>solix_to_xstring( lt_mail_body_solix ).
lo_bcs_message->set_main_doc(
EXPORTING
iv_contents_bin = l_content_bin
iv_doctype = 'htm'
).
TRY.
lo_bcs_message->send( ).
CATCH cx_bcs_send. "
ENDTRY.
Entscheidend ist hier der Abgleich der Mailadresse mit dem Benutzerstamm aus Sicherheitsgründen, die Generierung eines neuen Passwortes und das Hinterlegen ebendieses im Benutzerstamm. Danach wird es noch per Mail versendet.
Passend wird natürlich noch eine SAPUI5-Anwendung für das Frontend erstellt. Der entscheidende Teil ist hier einfach nur der Aufruf des oData-Service mit den entsprechenden Daten und eine Ausgabe der Meldung.
sap.ui.define(["sap/ui/core/mvc/Controller", "sap/m/MessageBox", "sap/m/MessageToast"], function (e, r, t) {
"use strict"; return e.extend("zflprpw.controller.Main", {
resetPassword: function () {
var e = this.getView().byId("uname_input").getValue(); var n = this.ge +
tView().byId("mail_input").getValue(); if (e === "" || n === "") {
r.error("Bitte Benutzername und E-Mail eingeben"); return }
var i = /^\w+[\w-+\.]*\@\w+([-\.]\w+)*\.[a-zA-Z]{2,}$/;
if (!n.match(i)) { r.error("Bitte eine korrekte Mailadresse eingeben"); return }
var a = {}; a.U + name=e; a.Mail = n; var s = this.getOwnerComponent().getModel(); s.create("/UserdataSet", a,
{ method: "POST", success: function (e) { t.show("E-Mail wurde gesendet") },
error: function (e) { r.error("Fehler beim Zurücksetzen des Kennworts") } })
}, back: function () {
window.history + .go(-1)
}
})
});
Letztendlich muss die entsprechende SAPUI5-Anwendung im SICF-Service für das Fiori Launchpad hinterlegt werden.
Hier ist auch entscheidend, dass für den Aufruf des “Passwort zurücksetzen”-Service ein entsprechender Systembenutzer im Service hinterlegt ist, damit dieser ohne Anmeldung aufgerufen werden kann.
Dabei wird kein CSRF-Token gesetzt. D.h. im Service sollte auch der Paramater ~CHECK_CSRF_TOKEN auf 0 gesetzt sein. (Gui-Konfiguration im SICF-Service)
Sollte man mehrere Mandanten im Frontend haben kann man auch einfach über externe Aliasse arbeiten.
[…] wieder Stellen wo SAP-seitig Passwörter generiert werden müssen. Ein Beispiel ist in dem Beitrag Service Passwort zurücksetzen auf dem Fiori Launchpad beschrieben. Was hierbei in heterogenen Landschaften aber nicht gleich bedacht ist sind die […]