2011年9月2日金曜日

[APEX]認証方式をLDAP認証にする



  • 概要
APEX4.0@Oracle11gではデフォルトのままではLDAP認証できない。
10gでは何の問題もなくWEB画面で設定するのみで認証できたがナゼ・・?
原因は不明でLDAP API作って実装しました
  • 経緯
SQL/PLUSで直接LDAP認証を試みてみる。

DECLARE
retval PLS_INTEGER;
my_session DBMS_LDAP.session;

BEGIN
retval:= -1;
my_session:= DBMS_LDAP.init('ldap.host.com',389);
retval:=DBMS_LDAP.simple_bind_s(my_session,'uid=my-id,ou=ldap,ou=host,c=com',my-password');
END;
エラーが…
ORA-31202: DBMS_LDAP: LDAP client/server error: Invalid credentials
いろいろ調べてみると…。

セキュリティーの為、UTL_TCP, UTL_HTTP, UTL_SMTP, UTL_MAIL, UTL_INADDRといったPL/SQLパッケージのメソッドを実行するには、ACLベースの権限を付与する必要がある。
ACL を付与するには、DBMS_NETWORK_ACL_ADMIN パッケージで行う。
存在するACL は、DBA_NETWORK_ACLS ,DBA_NETWORK_ACL_PRIVILEGES ビューで参照可能。

とのこと。
おそらくLDAP通信にてUTL_TCPあたりのパッケージを使っているのだろう。

sqlplusにてDBAでログイン
SQL> conn test/test@xe as sysdba
現在の状況を確認
select * from dba_network_acls;
select * from dba_network_acl_privileges;
APEXでLDAP認証できるように、ACLを作成(ldap.xmlは任意のACL名?、スキーマ名はEDU、ldap.host.comはホスト名)

begin
-- ACLを作成
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL('ldap.xml', 'ACL for ldap', 'EDU',true,'connect');
-- ユーザーにACLで定義した権限を割り当て
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE('ldap.xml','EDU',true,'resolve');
-- ACLに対応する接続先を割り当て
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL('ldap.xml','ldap.host.com');
end;
/

正常に設定されると以下のメッセージが表示される。
PL/SQL procedure successfully completed.
ACLを削除するときは以下のプロシージャを実行します。
DBMS_NETWORK_ACL_ADMIN.DROP_ACL('ldap.xml');

と、これでうまくいくはずだったのですが結局できず…
以下のファンクションを作って対処することになりました…
むむぅ・・・

-----
create or replace function LDAP_AUTH(p_username in varchar2, p_password in varchar2)
return BOOLEAN
is

userdn varchar2(4000);
userpassword varchar2(4000);

retval PLS_INTEGER;
my_session DBMS_LDAP.session;

begin
-- 認証対象のユーザのDN
userdn:= 'uid=' || p_username || ',ou=ldap,ou=host,o=com';
userpassword:= p_password;

retval:= -1;
my_session:= DBMS_LDAP.init('ldap.host.com',389);
retval:= DBMS_LDAP.simple_bind_s(my_session, userdn, userpassword);

 if (retval = -1) then
   return false;
 else
   return true;
 end if;

end;

[APEX]オートナンバー機能を実現するにはシーケンスを作成してからトリガを作成すること



  • 概要
APEX Oracle11gシーケンスオブジェクトを作成してからトリガを作成すること
APEXでテーブル定義をエクスポートしたが、中途半端にしかエクスポートされてないんだなとはまった話

  • 経緯
今、コメントを登録するためのアプリケーションをAPEXで作っています。

WEBインターフェースから必要な項目を入力するとOracleのテーブルにインサートされます。
対象のテーブル「COMMENT」テーブルにはIDとして自動で連番を振るようにしています。
つまり、オートナンバー機能を持たせています。

開発用(10g)のAPEX(3.x)から運用用(11gXE)のAPEX(4.x)にテーブル定義をエクスポートしてみたが、
トリガはエクスポートされるものの、シーケンスオブジェクトはエクスポートされねえんだな。

ずいぶんはまった。

シーケンスオブジェクトがないのにトリガを作成しようとすると
以下のエラーになります。

Compilation failed, line 3 (18:35:12) The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PL/SQL: ORA-02289: sequence does not existCompilation failed, line 3 (18:35:12) The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PL/SQL: SQL Statement ignored


  • 対応策
シーケンスオブジェクトを作成する

create sequence "<シーケンス名>"
start with <開始番号>
increment by <カウントアップ数>
maxvalue <最大数>
minvalue <最小数>
nocache <事前にメモリにキャッシュしておくか>
nocycle <繰り返し有無>
noorder <設定どおりの順序でナンバリングするか>
/


create sequence "TEST_SEQ"
start with 1
increment by 1
maxvalue 100
minvalue 1
nocache
nocycle
noorder
/


トリガを作成する

create or replace TRIGGER  "<トリガ名>"
BEFORE INSERT ON "<トリガを作成するテーブル名>"

FOR EACH ROW

BEGIN
 IF :NEW.<列名> IS NULL THEN
   SELECT <シーケンスオブジェクト名>.NEXTVAL INTO :NEW.<列名> FROM DUAL;
 END IF;
END;


create or replace TRIGGER  "TEST_ID"
BEFORE INSERT ON "TEST_TABLE"

FOR EACH ROW

BEGIN
 IF :
NEW.ID IS NULL THEN
   SELECT TEST_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
 END IF;
END;


11gから直接シーケンスオブジェクトにアクセス(値を挿入)できるようだが
うまくいかなかったのであきらめることにした。

動かなかった
原因はおいおい考えるとして…間違っているSQLをメモ。

NEW."ID" := TEST_SEQ.NEXTVAL