How to create custom login in Oracle APEX with custom Table.
1. Sequenz
/*============================= ====== TEST_SEQ =============== =============================*/ CREATE SEQUENCE TEST_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE ;
2. Table
CREATE TABLE "USERS" ( "ID" NUMBER DEFAULT "ABO_SEQ"."NEXTVAL", "NAME" VARCHAR2(4000) NOT NULL ENABLE, "EMAIL" VARCHAR2(4000) DEFAULT null, "PASSWORD" VARCHAR2(4000) DEFAULT null, "ACTIVE_YN" VARCHAR2(20) DEFAULT null, "LAST_LOGIN" TIMESTAMP (6) DEFAULT null -- foreign key , "ROLE_FK" NUMBER NOT NULL ENABLE, "REMARK" VARCHAR2(4000) DEFAULT null, "CREATED" TIMESTAMP (6) NOT NULL ENABLE, "CREATED_BY" VARCHAR2(4000) NOT NULL ENABLE, "UPDATED" TIMESTAMP (6) NOT NULL ENABLE, "UPDATED_BY" VARCHAR2(4000) NOT NULL ENABLE, "VALID_FROM" TIMESTAMP (6) NOT NULL ENABLE, "VALID_TO" TIMESTAMP (6) NOT NULL ENABLE, "DELETED_YN" VARCHAR2(4) DEFAULT 'NO', PRIMARY KEY ("ID") USING INDEX ENABLE )
3. History Table
CREATE TABLE "H_USER" ( "H_ID" NUMBER DEFAULT "ABO_SEQ"."NEXTVAL", "ID" NUMBER NOT NULL ENABLE, "NAME" VARCHAR2(4000) NOT NULL ENABLE, "EMAIL" VARCHAR2(4000) DEFAULT null, "PASSWORD" VARCHAR2(4000) DEFAULT null, "ACTIVE_YN" VARCHAR2(20) DEFAULT null, "LAST_LOGIN" TIMESTAMP (6) DEFAULT null -- foreign key , "ROLE_FK" NUMBER NOT NULL ENABLE, "REMARK" VARCHAR2(4000) DEFAULT null, "CREATED" TIMESTAMP (6) NOT NULL ENABLE, "CREATED_BY" VARCHAR2(4000) NOT NULL ENABLE, "UPDATED" TIMESTAMP (6) NOT NULL ENABLE, "UPDATED_BY" VARCHAR2(4000) NOT NULL ENABLE, "VALID_FROM" TIMESTAMP (6) NOT NULL ENABLE, "VALID_TO" TIMESTAMP (6) NOT NULL ENABLE, "DELETED_YN" VARCHAR2(4) NOT NULL ENABLE, "H_CREATED" TIMESTAMP (6) DEFAULT sysdate, PRIMARY KEY ("H_ID") USING INDEX ENABLE )
4. Trigger
CREATE OR REPLACE EDITIONABLE TRIGGER "TRG_H_USERS_TABLE" AFTER Insert or update ON users FOR EACH ROW DECLARE v_check_get_old_h_id number; v_get_old_h_id number; BEGIN -- check if old history row exits select count(*) into v_check_get_old_h_id from dual where exists(select * from h_user_table where id = :new.id ) ; --if yes if v_check_get_old_h_id = 1 then -- get last max id select max(h_id) into v_get_old_h_id from h_user_table where id = :new.id ; -- set valid to, to the max id row update h_user_table set valid_to = :new.valid_from where h_id = v_get_old_h_id ; end if; INSERT INTO h_user_table( id -- table column , name , email , password , Active_yn ,last_login -- foreign key , Role_fk -- audit , remark , created , created_by , updated , updated_by , valid_from , valid_to , deleted_yn ) VALUES ( :new.id -- table column , :new.name , :new.email , :new.password , :new.Active_yn , :new.last_login -- foreign key , :new.Role_fk -- audit , :new.remark , :new.created , :new.created_by , :new.updated , :new.updated_by , :new.valid_from , :new.valid_to , :new.deleted_yn ) ; END; / ALTER TRIGGER "TRG_H_USERS_TABLE" ENABLE /
specification
create or replace PACKAGE "AUTHENTICATION" is function hash_pass( pi_email in varchar2 default null , pi_password in varchar2 default null ) return varchar2 ; Function Authenticate_User(p_User_Name Varchar2 ,p_Password Varchar2) Return Boolean; Procedure Process_Login(p_User_Name Varchar2 ,p_Password Varchar2 ,p_App_Id Number); end authentication;
body
create or replace PACKAGE BODY "AUTHENTICATION" is function hash_pass( pi_email in varchar2 default null , pi_password in varchar2 default null ) return varchar2 is v_hash_pass varchar2(4000); v_salt varchar2(4000) := 'hdjikndbbhitasuihfnnkqyhiplwmneuyndnloidj'; begin v_hash_pass := DBMS_CRYPTO.Hash ( UTL_I18N.STRING_TO_RAW ( pi_password || substr(v_salt,10,13) || LOWER (pi_email) || substr(v_salt, 4,10) , 'AL32UTF8'), 2) ; return v_hash_pass; end hash_pass; ------------------------------------------------------------------------------- -- Login for admin ------------------------------------------------------------------------------- Function Authenticate_User(p_User_Name Varchar2 ,p_Password Varchar2) Return Boolean As v_Password varchar2(4000); v_Email varchar2(4000); v_Active_yn varchar2(4000); v_deleted_yn varchar2(4000); v_name varchar2(4000); Begin Begin Select EMAIL , PASSWORD , Active_yn , deleted_yn , null Into v_Email , v_Password , v_Active_yn , v_deleted_yn , v_name From USERS Where lower(EMAIL) = (p_User_Name); -- User not found Exception When No_Data_Found Then raise_application_error (-20001,'Benutzer nicht gefunden!'); Return False; End; -- passwort not match If v_Password <> authentication.hash_pass(lower(p_User_Name),p_Password) Then raise_application_error (-20001,'Passwort ist falsch!'); Return False; End If; -- user is not active or deleted If v_Active_yn = 'NO' or v_deleted_yn = 'YES' Then raise_application_error (-20001,'Benutzer ist gelöscht, bitte Admin kontaktieren!'); Return False; End If; Return True; End; -------------------------------------- Procedure Process_Login(p_User_Name Varchar2 ,p_Password Varchar2 ,p_App_Id Number ) As v_Result Boolean := False; Begin -- authenticate the user v_Result := Authenticate_User(p_User_Name , p_Password ); If v_Result = True Then -- save last login update USERS set last_login = sysdate where lower(email) = lower(p_User_Name); -- Redirect to Page 1 (Home Page). Wwv_Flow_Custom_Auth_Std.Post_Login(p_User_Name -- p_User_Name ,p_Password -- p_Password ,v('APP_SESSION') -- p_Session_Id ,p_App_Id || ':1' -- p_Flow_page ); Else -- Login Failure, redirect to page 9999 (Login Page). Owa_Util.Redirect_Url('f?p=&APP_ID.:9999:&SESSION.'); End If; End; end authentication;
APEX page
/*apex_authentication.login( p_username => :P9999_USERNAME, p_password => :P9999_PASSWORD, p_set_persistent_auth => nvl(:P9999_PERSISTENT_AUTH, 'N') = 'Y' ); */ authentication.Process_Login( p_User_Name => :P9999_USERNAME , p_Password => :P9999_PASSWORD , p_App_Id => :APP_ID );
Authentification
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.