APEX内置验证与授权管理

参考博客:(真的很好的教程,感谢!)

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

2023.8.28回来打补丁,完整实现见

Apex导航菜单权限动态分配的实现_王小小鸭的博客-CSDN博客icon-default.png?t=N6B9https://blog.csdn.net/clover_oreo/article/details/132532608?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22132532608%22%2C%22source%22%3A%22clover_oreo%22%7D

创建动态列表:

范例:

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: 此处不允许虚拟列

解决方法:用自定义的修改进行添加即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值