参考博客:(真的很好的教程,感谢!)
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
is
b_ret boolean :=false;
c_1 number;
begin
select count(1) into c_1 from test_user_wxx_v
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函数体:传入当前登录用户和当前页面
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_ID
regexp_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_ID
from TEST_USER_WXX_V where USER_NAME = :USER_NAME;
设置以上动态列表为导航菜单:
应用以后user普通用户果然只能打开首页,但是demo管理员用户也无法打开其他界面,坏了,紧急还原
看来还得好好学学登录后验证过程
验证过程3
-- 登录后验证过程3
CREATE PROCEDURE TEST_USER_WXX3_PRO AS
V_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,
EMAIL
INTO V_ROLE_ID,V_PERM_ID,V_USER_ID, V_USER_NAME, V_JOB_NUMBER, V_MOBILE, V_EMAIL
FROM TEST_USER_WXX_V
where USER_NAME = upper(V('P9999_USERNAME'));
-- 获取用户角色权限
SELECT COUNT(1)
INTO V_COUNT
FROM ROLE_USER_TEST_WXX A
LEFT JOIN TEST_ROLE_PERM_WXX_V B
ON A.ROLE_ID = B.ROLE_ID
WHERE A.USER_ID = V_USER_ID;
SELECT nvl(max(ROLE_ID), 0), nvl(max(PERM_ID), 0)
INTO V_ID, V_PAGE_ID
FROM TEST_ROLE_PERM_WXX_V
WHERE IS_ENABLE = 1;
IF V_COUNT > 0 THEN
SELECT A.ROLE_ID, B.PERM_ID
INTO V_ID, V_PAGE_ID
FROM ROLE_USER_TEST_WXX A
LEFT JOIN TEST_ROLE_PERM_WXX_V B
ON A.ROLE_ID = B.ROLE_ID
WHERE A.USER_ID = V_USER_ID
AND ROWNUM = 1;
ELSE
INSERT INTO ROLE_USER_TEST_WXX (USER_ID, ROLE_ID) VALUES (V_USER_ID, V_ID);
COMMIT;
END IF;
-- 设置USER
APEX_CUSTOM_AUTH.SET_USER(V_USER_NAME);
-- 将用户登入录信息注入session state
APEX_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 AS
V_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,
EMAIL
INTO V_DEPT_ID,V_ROLE_ID,V_PERM_ID,V_USER_ID, V_USER_NAME, V_JOB_NUMBER, V_MOBILE, V_EMAIL
FROM TEST_USER_WXX_V
where USER_NAME = upper(V('P9999_USERNAME'));
-- 获取用户角色权限
SELECT COUNT(1)
INTO V_COUNT
FROM TEST_USER_WXX_V A
LEFT JOIN TEST_ROLE_PERM_WXX_V B
ON A.ROLE_ID = B.ROLE_ID
WHERE A.USER_ID = V_USER_ID;
SELECT nvl(max(ROLE_ID), 0), nvl(max(PERM_ID), 0)
INTO V_ID, V_PAGE_ID
FROM TEST_ROLE_PERM_WXX_V
WHERE IS_ENABLE = 1;
IF V_COUNT > 0 THEN
SELECT A.ROLE_ID, B.PERM_ID
INTO V_ID, V_PAGE_ID
FROM ROLE_USER_TEST_WXX A
LEFT JOIN TEST_ROLE_PERM_WXX_V B
ON A.ROLE_ID = B.ROLE_ID
WHERE A.USER_ID = V_USER_ID
AND ROWNUM = 1;
ELSE
INSERT INTO ROLE_USER_TEST_WXX (USER_ID, ROLE_ID) VALUES (V_USER_ID, V_ID);
COMMIT;
END IF;
-- 设置USER
APEX_CUSTOM_AUTH.SET_USER(V_USER_NAME);
-- 将用户登入录信息注入session state
APEX_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
as
t_jobnumber varchar2(20);
t_password varchar2(20);
t_count number(10);
T_TENANT NUMBER;
begin
T_TENANT := apex_util.get_session_state('P9999_USER_TENANT');
select count(1)
into t_count
from TEST_USER_WXX_V
where upper(MOBILE) = upper(p_username)
and IS_LEAVE = 0;
if t_count > 0 then
select count(1) into t_count from TEST_USER_WXX_V
where MOBILE = upper(p_username);
else
insert 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,
SYSDATE
FROM TEST_USER_WXX_V
WHERE MOBILE = upper(p_username);
COMMIT;
update APEX_TENANT_USERS
set PASSWORD = ENCRYPT_ENC('123456')
where MOBILE = upper(p_username)
AND TENANT_ID = T_TENANT;
commit;
select MOBILE, PASSWORD
into t_jobnumber,t_password
from APEX_TENANT_USERS
where 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) then
apex_util.set_custom_auth_status(p_status => '手机号和密码不能为空');
return false;
else
if ENCRYPT_ENC(p_password) <> t_password then
apex_util.set_custom_auth_status(p_status => '手机号或密码错误');
return false;
else
return 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 AS
V_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,
EMAIL
INTO V_DEPT_ID,V_ROLE_ID,V_PERM_ID,V_USER_ID, V_USER_NAME, V_JOB_NUMBER, V_MOBILE, V_EMAIL
FROM TEST_USER_WXX_V
where USER_NAME = upper(V('P9999_USERNAME'));
-- 获取用户角色权限
SELECT COUNT(1)
INTO V_COUNT
FROM TEST_USER_WXX_V A
LEFT JOIN TEST_ROLE_PERM_WXX_V B
ON A.ROLE_ID = B.ROLE_ID
WHERE A.USER_ID = V_USER_ID;
SELECT nvl(max(ROLE_ID), 0), nvl(max(PERM_ID), 0)
INTO V_ID, V_PAGE_ID
FROM TEST_ROLE_PERM_WXX_V
WHERE IS_ENABLE = 1;
IF V_COUNT > 0 THEN
SELECT A.ROLE_ID, B.PERM_ID
INTO V_ID, V_PAGE_ID
FROM ROLE_USER_TEST_WXX A
LEFT JOIN TEST_ROLE_PERM_WXX_V B
ON A.ROLE_ID = B.ROLE_ID
WHERE A.USER_ID = V_USER_ID
AND ROWNUM = 1;
ELSE
INSERT INTO ROLE_USER_TEST_WXX (USER_ID, ROLE_ID) VALUES (V_USER_ID, V_ID);
COMMIT;
END IF;
-- 设置USER
APEX_CUSTOM_AUTH.SET_USER(V_USER_NAME);
-- 将用户登入录信息注入session state
APEX_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: 此处不允许虚拟列
解决方法:用自定义的修改进行添加即可