커스텀 사용자 테이블로 인증하고 로그인하기 두 번째 포스트입니다.
사용자 테이블 및 관리 페이지 세팅은 첫 번째 포스트를 참조하세요.
목차
기존의 인증 패키지
앱을 신규로 생성하면 기본적으로 9999번 페이지가 로그인 페이지로 생성이 됩니다.
이 로그인 페이지의 Processes를 보면 Login 이라는 이름을 가진 프로세스가 있습니다.
여기서 사용하는 로그인 패키지는 APEX_AUTHENICATION 이라는 APEX 내장 패키지입니다. 이 패키지의 LOGIN 프로시저를 사용해서 파라미터를 전달해서 로그인 처리를 진행하는 것이죠.
이 패키지를 우리가 만드는 패키지로 교체해서 커스텀 인증을 진행할 수 있습니다.
신규 함수 생성
앞선 포스트에서 SQL Command에서 STANDARD_HASH 함수를 사용해서 패스워드의 해시값을 저장할 수 있었습니다.
INSERT INTO APEX_USERS (
USER_ID,
USER_NAME,
USER_DEPARTMENT,
PASSWORD_HASH
) VALUES (
'john',
'존',
'인사팀',
STANDARD_HASH('apex', 'SHA256')
);
SQL
복사
그런데 APEX 패키지에서는 이 함수를 바로 사용할 수가 없어서 별도로 함수를 하나 만들어주어야 합니다.
SQL Workshop의 Object Browser로 이동해서 함수를 신규로 생성합시다. 해시되지 않은 패스워드를 받으면 해시된 값을 리턴하는 함수입니다.
CREATE OR REPLACE FUNCTION "GET_PASSWORD_HASH" (password IN VARCHAR2)
RETURN VARCHAR2
AS
v_password_hash VARCHAR2(255);
BEGIN
SELECT STANDARD_HASH(password, 'SHA256') INTO v_password_hash FROM DUAL;
RETURN v_password_hash ;
END "GET_PASSWORD_HASH";
SQL
복사
신규 패키지 생성
이제 SQL Workshop의 Object Browser로 이동해서 패키지를 신규로 생성합시다.
패키지는 기본적으로 Specification과 Body로 구성됩니다.
Specification에서는 Body에서 어떤 프로시저와 함수가 있는지 파라미터와 함께 정의하는 역할을 하고, 실제 프로시저와 함수는 Body에서 작성합니다.
Specification
다음과 같이 프로시저 1개와 함수 1개를 정의합니다.
CREATE OR REPLACE PACKAGE "AUTOOFFICE_AUTH" AS
PROCEDURE LOGIN (
p_userid IN VARCHAR2,
p_password IN VARCHAR2
);
FUNCTION AUTH (
p_userid VARCHAR2,
p_password VARCHAR2
) RETURN BOOLEAN;
END "AUTOOFFICE_AUTH";
SQL
복사
Body
Body에서 상세히 코드를 작성합니다.
CREATE OR REPLACE PACKAGE BODY "AUTOOFFICE_AUTH" AS
PROCEDURE LOGIN (
p_userid IN VARCHAR2,
p_password IN VARCHAR2
)
IS
v_result BOOLEAN := FALSE;
BEGIN
v_result := AUTOOFFICE_AUTH.AUTH(p_userid, p_password);
IF v_result = TRUE THEN
wwv_flow_custom_auth_std.post_login(p_userid, p_password, v('APP_SESSION'), '100:1');
ELSE
raise_application_error(-20001, '인증 실패');
END IF;
END LOGIN;
FUNCTION AUTH (
p_userid VARCHAR2,
p_password VARCHAR2
) RETURN BOOLEAN IS
v_password_hash VARCHAR2(255);
BEGIN
IF p_userid IS NULL OR p_password IS NULL THEN
raise_application_error(-20001, '아이디와 비밀번호를 입력해주세요.');
RETURN FALSE;
END IF;
SELECT PASSWORD_HASH INTO v_password_hash FROM APEX_USERS
WHERE lower(user_id) = lower(p_userid);
IF v_password_hash = GET_PASSWORD_HASH(p_password) THEN
-- 로그인 성공
RETURN TRUE;
ELSE
raise_application_error(-20001, '비밀번호가 일치하지 않습니다.');
RETURN FALSE;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise_application_error(-20001, '존재하지 않는 사용자입니다.');
RETURN FALSE;
END AUTH;
END "AUTOOFFICE_AUTH";
SQL
복사
AUTH 함수
AUTH 함수는 id와 password를 받아서 APEX_USERS 테이블에서 조회하고, 인증하는 함수입니다.
•
id와 password 중 하나라도 null이면 오류를 발생시킵니다.
•
id로 셀렉트 되는 값이 없으면 오류를 발생시킵니다.
•
APEX_USERS에서 조회된 해시값과 입력받은 password의 해시값이 일치하면 인증이 성공되고 TRUE를 반환하고, 그렇지 않으면 오류를 발생시킵니다.
APEX_USERS를 조회할 때에 id에 lower 함수를 적용한 것에 유의하세요. DB에는 id가 소문자로만 저장되도록 만들겠지만, 이렇게 처리해서 예외 상황을 방지합니다.
미리 만들어두었던 GET_PASSWORD_HASH 함수도 호출해서 사용합니다.
LOGIN 프로시저
AUTH 함수를 통해서 인증값을 TRUE 또는 FALSE로 받는 것에 따라 후속 조치를 진행합니다.
•
FALSE를 받은 경우에는 오류를 발생시킵니다.
•
TRUE를 받은 경우에는 로그인이 정상적으로 되었다는 것을 APEX에 알려주어야 하는데 이 코드가 그 역할을 합니다. 매개변수로 id, password, session 값, 포워딩 될 페이지를 전달합니다.
wwv_flow_custom_auth_std.post_login(p_userid, p_password, v('APP_SESSION'), '100:1');
SQL
복사
신규 패키지 적용
이제 패키지를 생성했으니, 9999번 로그인 페이지로 가서 프로세스를 수정하겠습니다.
Login 프로세스에서 Package를 신규 생성한 패키지 (AUTOOFFICE_AUTH)로 변경합니다.
Procedure or Function 은 LOGIN을 선택합니다.
Parameter를 지정해줍니다.
p_userid에는 P9999_USERNAME을 지정하고, p_password에는 P9999_PASSWORD를 지정합니다.
마지막으로 Shared Components > Authentication Scheme 에 신규 인증 스킴을 추가해줍니다.
이름을 정하고, Make Current Scheme을 눌러서 사용하는 스킴으로 지정해줍니다.
커스텀 로그인 적용 확인
이제 커스텀 로그인 세팅이 완료되었습니다. 적용되었는지 확인해볼까요?
로그인 페이지로 이동해서 기존의 APEX Accounts로 로그인을 시도하면 존재하지 않는 사용자라고 오류가 표시됩니다.
APEX_USERS 테이블에 생성한 john으로 로그인을 시도해봅니다.
로그인이 성공하며 Home인 1번 페이지로 로그인이 됩니다.