In this blog , we will go through step by step process to modify SAP Fiori Launchpad logon page (specifically adding CAPTCHA feature in SAP Private Cloud/on-prem System).
(1) Setup SAP backend system in ADT. You can refer this learning journey for the same Create an ABAP Project in ABAP Development Tools (ADT) | SAP Tutorials
(2) Once setup is completed create a new development package in ADT , for that follow below steps:
(a) Right click on Favorite Packages -> New -> ABAP Package
(b) Enter values as highlighted below in screenshots :
(3) We will now create a custom BSP application so that we can try-out our custom logon screen without impacting end-users. For this follow below steps :
(a) Right click on ZFIORI_CUSTOM_LOGON -> New -> Other ABAP Repository Object
(b) Search for "BSP" keyword and select "BSP Application"
(c) Give the BSP object name , this will be used for testing
(d) Activate the newly created BSP page , by clicking on Activate button
(e) Go to "sicf" tcode to test service
(f) You might get Authorization error like below , please note that as of now we just want to test if the object is active or not
(4) Now we will create a custom class in order to redefine standard logon class. In order to procced , follow below steps :
(a) Create a new class inside the same package
(b) Give below details and click Next
(c) Give TR details and click on Finish
(5) Copy this code snippet and paste it in our custom ZCL_CUSTOM_FIORI_LOGIN class :
CLASS zcl_custom_fiori_login DEFINITION
PUBLIC
INHERITING FROM /ui2/cl_fiori3_login
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_custom_fiori_login IMPLEMENTATION.
ENDCLASS.(6) We will now create custom JavaScript file which will be called during logon page load by following below steps :
(a) Create a file "zlogin_ext.js" and paste this code snippet :
/*!
* SAP Fiori login - add CAPTCHA along with Refresh button for the same
*/
document.addEventListener( 'DOMContentLoaded', (event) => {
const w = "white";
if (document.getElementById("LOGIN_LINK") !== null) {
document.getElementById("CHANGE_PASSWORD_LINK").style.color = w;
// Function to get the CAPTCHA name
function getCaptchaValue() {
var alpha = new Array("A", "B", "C", "D", "E", "F", "G","H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W","X", "Y", "Z", "a", "b", "c", "d",
"e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
"y", "z");
var i;
for (i = 0; i < 6; i++) {
var a = alpha[Math.floor(Math.random() * alpha.length)];
var b = Math.ceil(Math.random() * 10) + "";
var c = alpha[Math.floor(Math.random() * alpha.length)];
var d = alpha[Math.floor(Math.random() * alpha.length)];
var e = Math.ceil(Math.random() * 10) + "";
var f = alpha[Math.floor(Math.random() * alpha.length)];
var g = alpha[Math.floor(Math.random() * alpha.length)];
}
var code = a + " " + b + " " + " " + c + " " + d + " " + e + " " + f + " " + g;
var bCode = code.split(" ").join("");
return bCode;
}
const captchaLabel = document.createElement("text");
captchaLabel.textContent = getCaptchaValue();
captchaLabel.setAttribute("for", "captchaField");
captchaLabel.style.fontSize = '24px';
const captchaInput = document.createElement("input");
captchaInput.setAttribute("type", "text");
captchaInput.setAttribute("id", "captchaField");
captchaInput.setAttribute("name", "CAPTCHA");
captchaInput.setAttribute("required", "true");
captchaInput.setAttribute("placeholder", "Please enter Captcha");
captchaInput.style.width = "280px";
captchaInput.style.fontSize = '15px';
captchaInput.style.height = "35px";
const passwordBlock = document.getElementById("PASSWORD_BLOCK");
const captchaBlock = document.createElement("div");
captchaBlock.id = "CAPTCHA_BLOCK";
const captchaLabelWrapper = document.createElement("div");
captchaLabelWrapper.style.display = "flex";
captchaLabelWrapper.style.alignItems = "center";
captchaLabelWrapper.appendChild(captchaLabel);
captchaLabelWrapper.style.marginBottom = "20px";
captchaLabelWrapper.style.marginTop = "20px";
const refreshButton = document.createElement("button");
refreshButton.innerHTML = "↻"; // Unicode refresh icon (clockwise arrows)
refreshButton.style.marginLeft = "50px";
refreshButton.style.padding = "5px 10px";
refreshButton.style.cursor = "pointer";
refreshButton.style.backgroundColor = "#5CACEE";
refreshButton.style.color = "white";
refreshButton.style.border = "none";
refreshButton.style.borderRadius = "3px";
refreshButton.style.fontSize = "30px";
captchaLabelWrapper.appendChild(refreshButton);
captchaBlock.appendChild(captchaLabelWrapper);
captchaBlock.appendChild(captchaInput);
passwordBlock.insertAdjacentElement('afterend', captchaBlock);
const messageDiv = document.createElement("div");
messageDiv.id = "captchaMessage";
messageDiv.style.color = "red";
messageDiv.style.marginTop = "5px";
captchaBlock.appendChild(messageDiv);
let displayedCaptcha = captchaLabel.textContent;
const userEnteredCaptcha = captchaInput.value;
const loginButton = document.getElementById("LOGIN_LINK");
loginButton.disabled = true;
function updateCaptcha() {
captchaLabel.textContent = getCaptchaValue();
displayedCaptcha = captchaLabel.textContent;
captchaInput.value = "";
loginButton.disabled = true;
messageDiv.textContent = "";
}
refreshButton.addEventListener('click', () => {
updateCaptcha();
});
captchaInput.addEventListener('input', () => {
if (document.getElementById("captchaField").value === displayedCaptcha) {
loginButton.disabled = false;
messageDiv.textContent = "";
} else {
loginButton.disabled = true;
messageDiv.textContent = "Please enter correct Captcha and click on Logon again";
}
});
//Event listener to enable or disable Standard Login button based on CAPTCHA validation
loginButton.addEventListener('click', (e) => {
if (displayedCaptcha === document.getElementById("captchaField").value) {
loginButton.closest('form').submit();
messageDiv.textContent = "";
} else {
e.preventDefault();
messageDiv.textContent = "Please enter correct Captcha";
}
})
}
})(b) The above JavaScript code snippet will basically create a "CAPTCHA" label and input field. Catpcha text will be displayed in the label. Along with that there will be additional "Refresh" button to get new Captcha. It also display error message
(c) Goto "se80" tcode and import this "zlogin_ext.js" file as a new MIME object in path SAP -> PUBLIC -> BC -> UI2 -> logon -> fiori3 -> js
(7) Now we need to call this custom "zlogin_ext.js" JavaScript file in our custom ZCL_CUSTOM_FIORI_LOGIN ABAP class , for that update this ABAP class code as below
CLASS zcl_custom_fiori_login DEFINITION
PUBLIC
INHERITING FROM /ui2/cl_fiori3_login
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
PROTECTED SECTION.
METHODS init_default_properties REDEFINITION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_custom_fiori_login IMPLEMENTATION.
METHOD init_default_properties.
super->init_default_properties( context ).
m_properties->set( name = 'extra_js' value = '/sap/public/bc/ui2/logon/fiori3/js/zlogin_ext.js' ).
ENDMETHOD.
ENDCLASS.(8) Now we can test our Logon screen by going to "SICF" tcode and running our custom service "ZCUSTOM_FIORI_L" which we have created for testing :
(9) Now we need to configure this in Standard Fiori Launchpad, for that follow below steps :
(a) Goto "SICF" tcode and in "Service Name" enter "FLP" and double click on the entry
(b) Switch to Edit mode
(c) Navigate to Error pages, activate the System Logon radio button and click on Configuration
(d) In the System Logon Configuration menu, activate radio button: Define Service-Specific Settings followed by activating radio button Custom Implementation and entering the name of your custom class (in our case it is ZCL_CUSTOM_FIORI_LOGIN). Once done, click on Ok button and accept all messages.
(e) Once changes have been done, click on Save.
NOTE - You will be prompted for a transport request
(10) Logon to the Fiori Launchpad(or you can directly use "/n/ui2/flp" tcode), you should now see the same new custom logon page which is been shown in step 8.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 24 | |
| 15 | |
| 14 | |
| 11 | |
| 9 | |
| 9 | |
| 9 | |
| 9 | |
| 9 | |
| 8 |