09技术太卷我学APEX-定制页面及导航菜单权限
0 始终没搞明白APEX的角色如果分配页面的权限,只能自己定制一个
APEX现学现卖开发了个《5217仓库管理》,功能在春节前就搞定了,卡在对页面的权限控制,经过翻阅牛人的博客,结合自己的经验终于搞定了。
1 权限管理设计
每个页面配置给自定义角色功能权限,也就是能看到和操作,还有页面对应的导航菜单,然后自定义用户可以配置多个角色,用户通过角色可以获得角色的功能权限。关系图大概如下图:
用户 | 角色 | 页面ID |
---|---|---|
白龙马 | 系统管理 | 10099 |
10100 | ||
10110 | ||
库管 | 410 | |
420 |
一个用户对多个角色,一个角色对多个页面。
1.1 数据库表设计
需要创建4个系统表,保存用户、角色及页面之间的关系。
- 角色表(角色ID,角色名称)
- 角色页面表(角色ID,页面ID)
- 用户表(用户ID,用户姓名,密码)
- 用户角色表(用户ID,角色ID)
--角色表
CREATE TABLE "SYS_ROLE"
( "P_ID" NUMBER(17,0) NOT NULL ENABLE,
"ROLE_NAME" VARCHAR2(17) NOT NULL ENABLE,
"S_NOTE" VARCHAR2(52),
CONSTRAINT "SYS_ROLE_PK" PRIMARY KEY ("P_ID")
USING INDEX ENABLE,
CONSTRAINT "SYS_ROLE_NAME" UNIQUE ("ROLE_NAME")
USING INDEX ENABLE
)
--角色页面表
CREATE TABLE "SYS_ROLE_PAGE"
( "P_ID" NUMBER(17,0) NOT NULL ENABLE,
"ROLE_NAME" VARCHAR2(17) NOT NULL ENABLE,
"PAGE_ID" NUMBER(17,0) NOT NULL ENABLE,
"S_NOTE" VARCHAR2(52),
CONSTRAINT "SYS_ROLE_PAGE_PK" PRIMARY KEY ("P_ID")
USING INDEX ENABLE,
CONSTRAINT "SYS_ROLE_PAGE_UK1" UNIQUE ("ROLE_NAME", "PAGE_ID")
USING INDEX ENABLE
)
--用户表
CREATE TABLE "SYS_USER"
( "P_ID" NUMBER(13,0) NOT NULL ENABLE,
"USER_NAME" VARCHAR2(17) NOT NULL ENABLE,
"PASS_WORD" VARCHAR2(17) NOT NULL ENABLE,
"S_MOBILE" VARCHAR2(17),
"S_EMAIL" NVARCHAR2(52),
"NICK_NAME" VARCHAR2(17),
CONSTRAINT "SYS_USER_PK" PRIMARY KEY ("P_ID")
USING INDEX ENABLE,
CONSTRAINT "SYS_USER_UK1_USER_NAME" UNIQUE ("USER_NAME")
USING INDEX ENABLE,
CONSTRAINT "SYS_USER_UK2_S_MOBILE" UNIQUE ("S_MOBILE")
USING INDEX ENABLE,
CONSTRAINT "SYS_USER_UK3_S_EMAIL" UNIQUE ("S_EMAIL")
USING INDEX ENABLE
)
--用户角色表
CREATE TABLE "SYS_USER_ROLE"
( "P_ID" NUMBER(17,0) NOT NULL ENABLE,
"USER_NAME" VARCHAR2(17) NOT NULL ENABLE,
"ROLE_NAME" VARCHAR2(17) NOT NULL ENABLE,
"S_NOTE" VARCHAR2(52),
CONSTRAINT "SYS_USER_ROLE_PK" PRIMARY KEY ("P_ID")
USING INDEX ENABLE,
CONSTRAINT "SYS_USER_ROLE_UK1" UNIQUE ("USER_NAME", "ROLE_NAME")
USING INDEX ENABLE
)
2 创建5个管理页面
2.1 角色管理
交互网格带编辑
2.2 角色页面管理
交互网格带编辑
创建角色值列表
创建页面值列表
select t.page_alias,t.page_id,t.page_name,t.page_title,t.page_mode,t.page_function
from APEX_APPLICATION_PAGES t
where application_id = :APP_ID
这里用到了APEX的视图;
两个值列表配置到角色和页面ID列。
2.3 用户管理
交互式网格+表单
2.4 用户角色管理
交互式网格加编辑
创建用户值列表
用户和角色值列表配置到用户和角色。
2.5 系统管理
以上4个页面做一个系统管理导航卡列表。
3 创建授权方案
3.1 创建一个授权控制函数F_CONTROL
create or replace function "F_CONTROL"
(p_username in VARCHAR2,
p_pageid in number)
return boolean
is
b_ret boolean :=false;
c_1 number;
begin
select count(1) into c_1 from v_sys_user_role_page
where user_name = p_username and page_id = p_pageid;
if (c_1 >= 1) then
b_ret := true;
else
b_ret := false;
end if;
return b_ret;
exception when others then
return false;
end;
3.2 创建授权方案
名称:随便自己输入
方案类型:返回布尔值的PL/SQL函数
PL/SQL函数体:传入当前登录用户和当前页面
求值点:每次页访问一次
4 页面授权控制
设置需求授权的页面设置安全性如下图:
这样设置后,就是直接在IP地址栏输入页面也需求授权许可。
需要授权的都设置上授权方案:
5 导航授权控制
设计是这样没有,根据登录帐户,没有授权的页面链接就不在导航菜单上显示了。目前为静态导航菜单,需要引用静态导航菜单的数据创建一个动态的导航菜单。
5.1 创建静态导航菜单的视图
这里用到APEX的系统视图,代码如下:
CREATE OR REPLACE FORCE EDITIONABLE VIEW "V_MY_MENU" ("PARENT_ENTRY_TEXT", "DISPLAY_SEQUENCE", "ENTRY_TEXT", "PAGE_ID", "ENTRY_TARGET") AS
select parent_entry_text,display_sequence,entry_text,
regexp_replace(entry_target,'[^0-9]') as page_id,entry_target
from apex_application_list_entries t
where application_id = 104313 and list_id = 38247996304963868908
order by t.display_sequence
这里用到Oracle的正则表达式替换函数提取出目标的页面id:regexp_replace(entry_target,‘[^0-9]’) as page_id
视图的数据如下:
5.2 创建动态导航菜单视图
这里只支持2级菜单。
代码如下:
CREATE OR REPLACE FORCE EDITIONABLE VIEW "CK_MENU_V" ("LEVEL_VALUE", "LABEL_VALUE", "TARGET_VALUE", "IS_CURRENT", "IMAGE_VALUE", "IMAGE_ATTR_VALUE", "IMAGE_ALT_VALUE", "DISPLAY_ORDER", "PAGE_ID") AS
select 1 as LEVEL_VALUE,entry_text as LABEL_VALUE,entry_target as TARGET_VALUE, '' as IS_CURRENT,
ENTRY_IMAGE as IMAGE_VALUE,'' as IMAGE_ATTR_VALUE,'' as IMAGE_ALT_VALUE, display_sequence as DISPLAY_ORDER,
regexp_replace(entry_target,'[^0-9]') as page_id
from apex_application_list_entries
where application_id = 104313 and list_id = 38247996304963868908 and parent_entry_text is null
union all
select 2 as LEVEL_VALUE,entry_text as LABEL_VALUE,entry_target as TARGET_VALUE, '' as IS_CURRENT,
ENTRY_IMAGE as IMAGE_VALUE,'' as IMAGE_ATTR_VALUE,'' as IMAGE_ALT_VALUE, display_sequence as DISPLAY_ORDER,
regexp_replace(entry_target,'[^0-9]') as page_id
from apex_application_list_entries
where application_id = 104313 and list_id = 38247996304963868908 and parent_entry_text is not null
order by DISPLAY_ORDER
数据如下:
5.3 创建一个动态列表并设置为导航菜单
创建动态列表:
动态列表SQL:
``
select * from ck_menu_v
where page_id in (
select distinct page_id from V_SYS_USER_ROLE_PAGE where user_name = :APP_USER
)
设置以上动态列表为导航菜单:

## 6 效果DEMO
到这里总算一切OK了,看一下效果:
### 6.1 系统管理

### 6.2 角色管理

### 6.3 角色页面管理

### 6.4 用户管理

### 6.5 用户角色管理

### 6.6 换APEX用户登录

没有了【系统管理】导航菜单,直接输入页面地址试试

也访问不了,第一行就是自定义的错误信息。
OK了,一个完整定制验证(验证参阅 01 技术太卷我学APEX-定制验证方案)和授权就完成了。