参考博客:(真的很好的教程,感谢!)
09技术太卷我学APEX-定制页面及导航菜单权限_白龙马5217的博客-CSDN博客https://blog.csdn.net/html5builder/article/details/128816236?spm=1001.2014.3001.5501
1 应用程序安全性设计
1.1 应用程序的验证/授权/会话管理
1.2 Apex 用户管理
需要在工作区管理项下创建用户,
1.3 用户访问控制
在【访问控制】-【用户】功能页设置领队的权限
定制页面与导航栏菜单权限
创建角色值列表
select name, name as rname from role_test_wxx2
创建页面值列表
select t.PAGE_ID,t.PAGE_PARENT_ID
from TEST_USER_WXX_V t
where APP_ID = :APP_ID;
创建用户值列表
用户和角色值列表配置到用户和角色。
select name, name as uname from user_test_wxx2
创建导航卡“系统管理_导航卡_Demo”
创建成功
点开还可以继续修改,设置图标
2 创建导航页面
Step 1创建空白页面
应用程序-创建页
Setp 2放置列表区域
拖放一个列表区域到页面上,开始只能放到面包屑区域,放置后,在左边的结构树可以拖放到body区下面。
Setp 3设置列表区域属性
导航卡之前
导航卡之后
3 创建授权方案
3.1 创建一个授权控制函数F_CONTROL
create or replace function "F_CONTROL"
(p_username in VARCHAR2,p_pageid in number)
return boolean
isb_ret boolean :=false;c_1 number;
beginselect count(1) into c_1 from test_user_wxx_vwhere user_name = p_username and page_id = p_pageid;if (c_1 >= 1) then b_ret := true;elseb_ret := false;end if; return b_ret;exception when others thenreturn false;
end;
3.2 创建授权方案
名称:随便自己输入
方案类型:返回布尔值的PL/SQL函数
PL/SQL函数体:传入当前登录用户和当前页面
return f_control(
p_username => :USER_ID,
p_pageid => :PAGE_ID
);
求值点:每次页访问一次
有问题
4 页面授权控制
设置需求授权的页面设置安全性如下图:
这样设置后,就是直接在IP地址栏输入页面也需求授权许可。
需要授权的都设置上授权方案:
5 导航授权控制
设计是这样没有,根据登录帐户,没有授权的页面链接就不在导航菜单上显示了。目前为静态导航菜单,需要引用静态导航菜单的数据创建一个动态的导航菜单。
5.1 创建静态导航菜单的视图test_menu_wxx_v
CREATE OR REPLACE FORCE EDITIONABLE VIEW "test_menu_wxx_v" ("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 = 273 and list_id = 128816236
order by t.display_sequence
这里用到Oracle的正则表达式替换函数提取出目标的页面id:regexp_replace(entry_target,‘[^0-9]’) as page_id
视图的数据如下:
CREATE OR REPLACE FORCE EDITIONABLE VIEW "test_menu_wxx_v" ( "ROLE_NAME","PERM_NAME", "PAGE_ID") AS select ROLE_NAME,PERM_NAME,PAGE_IDregexp_replace(entry_target,'[^0-9]') as page_id,entry_target
from test_user_wxx_v t
where application_id = 273 and list_id = 128816236/17346944776181
5.2 创建动态导航菜单视图
自己的:
创建角色权限视图TEST_ROLE_PERM_WXX_V
-- 创建视图 角色权限
create view TEST_ROLE_PERM_WXX_V as
select distinct rp.ROLE_PERM_ID,rp.ROLE_ID as ROLE_ID,rp.PERM_ID as PERM_ID,rp.IS_ENABLE,rp.REMARK,r.NAME as ROLE_NAME,p.NAME as PERM_NAME,p.PAGE_ID as PAGE_ID
from ROLE_PERM_TEST_WXX rp
LEFT JOIN ROLE_TEST_WXX2 r on r.ROLE_ID = rp.ROLE_ID
LEFT JOIN PERM_TEST_WXX2 p on p.PERM_ID = rp.PERM_ID;
查询效果
创建角色用户视图 TEST_ROLE_USER_WXX_V
-- 创建角色用户视图 TEST_ROLE_USER_WXX_V
create view TEST_ROLE_USER_WXX_V as
select distinct ROLE_USER_ID,ru.ROLE_ID as ROLE_ID,ru.USER_ID as USER_ID,r.NAME as ROLE_NAME,u.NAME as USER_NAME,u.MOBILE,u.JOB_NUMBER,u.PASSWORD,u.EMAIL,u.DEVELOPER_ID
from ROLE_USER_TEST_WXX ru
LEFT JOIN ROLE_TEST_WXX2 r on r.ROLE_ID = ru.ROLE_ID
LEFT JOIN USER_TEST_WXX2 u on u.USER_ID = ru.USER_ID;
效果:
5.3 创建一个动态列表并设置为导航菜单test_menu_wxx_v
创建动态列表:
范例:
select * from ck_menu_v
where page_id in (
select distinct page_id from V_SYS_USER_ROLE_PAGE where user_name = :APP_USER
)
我的:
select * from TEST_USER_WXX_V where USER_NAME = :USER_NAME;
???为什么呀?百思不得其解
不加条件查询到的数据
代码:
select USER_ID,USER_NAME,DEPT_ID,DEPT_NAME,ROLE_ID,ROLE_NAME,PERM_ID,PERM_NAME,PAGE_ID from TEST_USER_WXX_V;
为什么传入一个user_name反而不行了?看来问题出在传入的user_name上
发现直接将值传入没问题
代码
-- 动态列表 传入user_name
select USER_ID,DEPT_ID,DEPT_NAME,ROLE_ID,ROLE_NAME,PERM_ID,PERM_NAME,PAGE_ID
from TEST_USER_WXX_V where USER_NAME = 'user';
最终:test_menu_wxx_v
select USER_ID,DEPT_ID,DEPT_NAME,ROLE_ID,ROLE_NAME,PERM_ID,PERM_NAME,PAGE_IDfrom TEST_USER_WXX_V where USER_NAME = :USER_NAME;
设置以上动态列表为导航菜单:
应用以后user普通用户果然只能打开首页,但是demo管理员用户也无法打开其他界面,坏了,紧急还原
看来还得好好学学登录后验证过程
验证过程3
-- 登录后验证过程3
CREATE PROCEDURE TEST_USER_WXX3_PRO ASV_USER_ID NUMBER(20);V_ROLE_ID NUMBER(20);V_PERM_ID NUMBER(20);V_DEPT_ID NUMBER(20);V_USER_NAME NVARCHAR2(64);V_JOB_NUMBER NVARCHAR2(32);V_MOBILE NVARCHAR2(32);V_EMAIL NVARCHAR2(32);V_COUNT NUMBER(10);V_ID NUMBER(10);V_DEPT_NAME NVARCHAR2(64);V_PAGE_ID NUMBER(20);begin-- 获取用户基础信息SELECT DEPT_ID,ROLE_ID,PERM_ID,USER_ID,USER_NAME,JOB_NUMBER,MOBILE,EMAILINTO V_ROLE_ID,V_PERM_ID,V_USER_ID, V_USER_NAME, V_JOB_NUMBER, V_MOBILE, V_EMAILFROM TEST_USER_WXX_Vwhere USER_NAME = upper(V('P9999_USERNAME'));-- 获取用户角色权限
SELECT COUNT(1)INTO V_COUNTFROM ROLE_USER_TEST_WXX ALEFT JOIN TEST_ROLE_PERM_WXX_V BON A.ROLE_ID = B.ROLE_IDWHERE A.USER_ID = V_USER_ID;SELECT nvl(max(ROLE_ID), 0), nvl(max(PERM_ID), 0)INTO V_ID, V_PAGE_IDFROM TEST_ROLE_PERM_WXX_VWHERE IS_ENABLE = 1;IF V_COUNT > 0 THENSELECT A.ROLE_ID, B.PERM_IDINTO V_ID, V_PAGE_IDFROM ROLE_USER_TEST_WXX ALEFT JOIN TEST_ROLE_PERM_WXX_V BON A.ROLE_ID = B.ROLE_IDWHERE A.USER_ID = V_USER_IDAND ROWNUM = 1;ELSEINSERT INTO ROLE_USER_TEST_WXX (USER_ID, ROLE_ID) VALUES (V_USER_ID, V_ID);COMMIT;END IF;-- 设置USERAPEX_CUSTOM_AUTH.SET_USER(V_USER_NAME);-- 将用户登入录信息注入session stateAPEX_UTIL.SET_SESSION_STATE('ROLE_ID', V_ID);APEX_UTIL.SET_SESSION_STATE('DEPT_ID', V_DEPT_ID);APEX_UTIL.SET_SESSION_STATE('USER_NAME', V_USER_NAME);APEX_UTIL.SET_SESSION_STATE('JOB_NUMBER', V_JOB_NUMBER);APEX_UTIL.SET_SESSION_STATE('MOBILE', V_MOBILE);APEX_UTIL.SET_SESSION_STATE('MAIL', V_EMAIL);APEX_UTIL.SET_SESSION_STATE('USER_ID', V_USER_ID);APEX_UTIL.SET_SESSION_STATE('DEPT_NAME', V_DEPT_NAME);
-- APEX_UTIL.SET_SESSION_STATE('USERID', V_USERID);
END;
/
遇到的问题
编译失败, 行 26 (15:42:45)
PL/SQL: ORA-00947: 没有足够的值编译失败, 行 17 (15:42:45)
PL/SQL: SQL Statement ignored
ORA-00947: 没有足够的值_ora00947没有足够的值_cbgYjch的博客-CSDN博客https://blog.csdn.net/cbgYjch/article/details/116670031破案了,少数据项了
最终校验过程3 TEST_USER_WXX3_PRO
create or replace PROCEDURE TEST_USER_WXX3_PRO ASV_USER_ID NUMBER(20);V_ROLE_ID NUMBER(20);V_PERM_ID NUMBER(20);V_DEPT_ID NUMBER(20);V_USER_NAME NVARCHAR2(64);V_JOB_NUMBER NVARCHAR2(32);V_MOBILE NVARCHAR2(32);V_EMAIL NVARCHAR2(32);V_COUNT NUMBER(10);V_ID NUMBER(10);V_DEPT_NAME NVARCHAR2(64);V_PAGE_ID NUMBER(20);begin-- 获取用户基础信息SELECT DEPT_ID,ROLE_ID,PERM_ID,USER_ID,USER_NAME,JOB_NUMBER,MOBILE,EMAILINTO V_DEPT_ID,V_ROLE_ID,V_PERM_ID,V_USER_ID, V_USER_NAME, V_JOB_NUMBER, V_MOBILE, V_EMAILFROM TEST_USER_WXX_Vwhere USER_NAME = upper(V('P9999_USERNAME'));-- 获取用户角色权限
SELECT COUNT(1)INTO V_COUNTFROM TEST_USER_WXX_V ALEFT JOIN TEST_ROLE_PERM_WXX_V BON A.ROLE_ID = B.ROLE_IDWHERE A.USER_ID = V_USER_ID;SELECT nvl(max(ROLE_ID), 0), nvl(max(PERM_ID), 0)INTO V_ID, V_PAGE_IDFROM TEST_ROLE_PERM_WXX_VWHERE IS_ENABLE = 1;IF V_COUNT > 0 THENSELECT A.ROLE_ID, B.PERM_IDINTO V_ID, V_PAGE_IDFROM ROLE_USER_TEST_WXX ALEFT JOIN TEST_ROLE_PERM_WXX_V BON A.ROLE_ID = B.ROLE_IDWHERE A.USER_ID = V_USER_IDAND ROWNUM = 1;ELSEINSERT INTO ROLE_USER_TEST_WXX (USER_ID, ROLE_ID) VALUES (V_USER_ID, V_ID);COMMIT;END IF;-- 设置USERAPEX_CUSTOM_AUTH.SET_USER(V_USER_NAME);-- 将用户登入录信息注入session stateAPEX_UTIL.SET_SESSION_STATE('ROLE_ID', V_ID);APEX_UTIL.SET_SESSION_STATE('DEPT_ID', V_DEPT_ID);APEX_UTIL.SET_SESSION_STATE('USER_NAME', V_USER_NAME);APEX_UTIL.SET_SESSION_STATE('JOB_NUMBER', V_JOB_NUMBER);APEX_UTIL.SET_SESSION_STATE('MOBILE', V_MOBILE);APEX_UTIL.SET_SESSION_STATE('MAIL', V_EMAIL);APEX_UTIL.SET_SESSION_STATE('USER_ID', V_USER_ID);APEX_UTIL.SET_SESSION_STATE('DEPT_NAME', V_DEPT_NAME);
-- APEX_UTIL.SET_SESSION_STATE('USERID', V_USERID);
END;
成功编译
到应用程序中验证
坏了,还是一样的情况,无论是user普通用户还是demo管理员账号都能看到QAQ
登录验证 TEST_LOGIN_WXX_FUN
-- 登录验证
create function TEST_LOGIN_WXX_FUN(p_username in varchar2,p_password in varchar2)return boolean
ast_jobnumber varchar2(20);t_password varchar2(20);t_count number(10);T_TENANT NUMBER;
beginT_TENANT := apex_util.get_session_state('P9999_USER_TENANT');select count(1)into t_countfrom TEST_USER_WXX_Vwhere upper(MOBILE) = upper(p_username)and IS_LEAVE = 0;if t_count > 0 thenselect count(1) into t_count from TEST_USER_WXX_Vwhere MOBILE = upper(p_username);elseinsert into USER_TEST_WXX2(USER_ID,NAME,GENDER,MOBILE,JOB_NUMBER,PASSWORD,EMAIL,DEVELOPER_ID,IS_LEAVE,REMARK,UPDATE_DATE)select USER_ID,NAME,GENDER,MOBILE,JOB_NUMBER,PASSWORD,EMAIL,DEVELOPER_ID,IS_LEAVE,REMARK,0,SYSDATEFROM TEST_USER_WXX_VWHERE MOBILE = upper(p_username);COMMIT;update APEX_TENANT_USERSset PASSWORD = ENCRYPT_ENC('123456')where MOBILE = upper(p_username)AND TENANT_ID = T_TENANT;commit;select MOBILE, PASSWORDinto t_jobnumber,t_passwordfrom APEX_TENANT_USERSwhere MOBILE = upper(p_username)AND TENANT_ID = T_TENANT;-- apex_util.set_custom_auth_status(p_status => '手机号不存在');
-- return false;end if;if (t_jobnumber is null or t_password is null) thenapex_util.set_custom_auth_status(p_status => '手机号和密码不能为空');return false;elseif ENCRYPT_ENC(p_password) <> t_password thenapex_util.set_custom_auth_status(p_status => '手机号或密码错误');return false;elsereturn true;end if;end if;end;
/
【错误记录】ORA-00904: "USER_PASSWORD": 标识符无效编译失败
编译失败, 行 29 (16:33:51)
PL/SQL: ORA-00904: "USER_PASSWORD": 标识符无效编译失败, 行 23 (16:33:51)
PL/SQL: SQL Statement ignored
内置验证与授权
插个眼
之前
之后
范例
css
#APP_IMAGES#app-icon.css?version=#APP_VERSION#
REST URL
oracle.dbtools.role.autorest.YWJA.TEST_USER_WXX3_PRO
【错误记录】ora_sqlerrm: ORA-01403: 未找到任何数据
为什么产生ORA-01403
ORA-01403: 未找到任何数据 异常主要是由于SQL中使用了SELECT INTO 但是根据条件没有查询到结果引起.
TEST_USER_WXX3_PRO代码
create or replace PROCEDURE TEST_USER_WXX3_PRO ASV_USER_ID NUMBER(20);V_ROLE_ID NUMBER(20);V_PERM_ID NUMBER(20);V_DEPT_ID NUMBER(20);V_USER_NAME NVARCHAR2(64);V_JOB_NUMBER NVARCHAR2(32);V_MOBILE NVARCHAR2(32);V_EMAIL NVARCHAR2(32);V_COUNT NUMBER(10);V_ID NUMBER(10);V_DEPT_NAME NVARCHAR2(64);V_PAGE_ID NUMBER(20);begin-- 获取用户基础信息SELECT DEPT_ID,ROLE_ID,PERM_ID,USER_ID,USER_NAME,JOB_NUMBER,MOBILE,EMAILINTO V_DEPT_ID,V_ROLE_ID,V_PERM_ID,V_USER_ID, V_USER_NAME, V_JOB_NUMBER, V_MOBILE, V_EMAILFROM TEST_USER_WXX_Vwhere USER_NAME = upper(V('P9999_USERNAME'));-- 获取用户角色权限
SELECT COUNT(1)INTO V_COUNTFROM TEST_USER_WXX_V ALEFT JOIN TEST_ROLE_PERM_WXX_V BON A.ROLE_ID = B.ROLE_IDWHERE A.USER_ID = V_USER_ID;SELECT nvl(max(ROLE_ID), 0), nvl(max(PERM_ID), 0)INTO V_ID, V_PAGE_IDFROM TEST_ROLE_PERM_WXX_VWHERE IS_ENABLE = 1;IF V_COUNT > 0 THENSELECT A.ROLE_ID, B.PERM_IDINTO V_ID, V_PAGE_IDFROM ROLE_USER_TEST_WXX ALEFT JOIN TEST_ROLE_PERM_WXX_V BON A.ROLE_ID = B.ROLE_IDWHERE A.USER_ID = V_USER_IDAND ROWNUM = 1;ELSEINSERT INTO ROLE_USER_TEST_WXX (USER_ID, ROLE_ID) VALUES (V_USER_ID, V_ID);COMMIT;END IF;-- 设置USERAPEX_CUSTOM_AUTH.SET_USER(V_USER_NAME);-- 将用户登入录信息注入session stateAPEX_UTIL.SET_SESSION_STATE('ROLE_ID', V_ID);APEX_UTIL.SET_SESSION_STATE('DEPT_ID', V_DEPT_ID);APEX_UTIL.SET_SESSION_STATE('USER_NAME', V_USER_NAME);APEX_UTIL.SET_SESSION_STATE('JOB_NUMBER', V_JOB_NUMBER);APEX_UTIL.SET_SESSION_STATE('MOBILE', V_MOBILE);APEX_UTIL.SET_SESSION_STATE('MAIL', V_EMAIL);APEX_UTIL.SET_SESSION_STATE('USER_ID', V_USER_ID);APEX_UTIL.SET_SESSION_STATE('DEPT_NAME', V_DEPT_NAME);
-- APEX_UTIL.SET_SESSION_STATE('USERID', V_USERID);
END;
导航菜单权限09
按下之后会这样
回去查看了列表,是对的鸭,应该差了东西
在每张表加上授权方案试试
表对应的页设计器→选中表→区域 安全性:自定义的方案
测试一下↓
加上安全性授权方案以后直接消失不见,普通用户user也就算了,管理员demo也不行QAQ
找原因ing
1.
2.
3.修改PL/SQL函数体
之前:
return f_control(p_username => :USER_NAME,p_pageid => :PAGE_ID
);
之后:
return f_control(p_username => :APP_NAME,p_pageid => :APP_PAGE_ID
);
原来是还没配置完orz
之前
之后
测试一下:
报的是我自定义的错误(标识方案违规时显示的错误消息)
应该是username和pageid未被传值
蒋老师小课堂
1.添加表单,源位置:本地数据库,类型一定要是SQL查询,不能是表/视图
2.PL/SQL开发和命名规范;
【错误记录】ORA-01733: 此处不允许虚拟列
解决方法:用自定义的修改进行添加即可