软件包语法问题

时间:2019-09-21 22:43:50

标签: oracle plsql plsql-package

我正在尝试创建一个名为MSGG_SESSION的程序包,该程序的过程身份验证接受用户名和密码的两个VARCHAR2参数。我想为当前人员ID放置一个package-private NUMBER变量。如果“ authenticate”与MSGG_USER中的用户名和密码匹配,则将匹配的PERSON_ID放入新变量中。在包中添加一个函数get_user_id,该函数返回包含人员ID的变量的值。

但是我有两个错误,说表或视图从not_authenticated_exception之前的第二个开始不退出

和sql语句从priv_number varchar2(100)开始被忽略。

CREATE OR REPLACE PACKAGE MSGG_SESSION IS

  PROCEDURE AUTHENTICATE (USERNAME_to_auth IN VARCHAR2, PASSWORD_to_use IN VARCHAR2);

  FUNCTION AUTHENTICATED_USER RETURN VARCHAR2;

END MSGG_SESSION;

 /



create or replace package body msgg_session is

 priv_number varchar2(100);

   procedure authenticate (username_to_auth in varchar2, password_to_use in varchar2)

   is     

    not_authenticated exception;

   begin

    select username

      into priv_number

     from user_password

    where lower(username) = lower(username_to_auth)

     and password = password_to_use;

  exception

    when no_data_found then     

     begin

      raise not_authenticated;

     exception

      when not_authenticated then

       raise_application_error(-20000, 'Not authenticated');

     end;

    when others then

     raise;

   end authenticate;   

  function authenticated_user

    return varchar2

   is

   begin

    return null;

   end;



   function get_user_id

    return varchar2

   is

   begin

    return priv_number;

   end get_user_id;

  end msgg_session;

  /

1 个答案:

答案 0 :(得分:1)

您没有提供表DDL或错误消息的行号,因此不清楚为什么会得到ORA-00942: table or view does not exist。检查表的拼写,确保表和包在同一模式中,并且双引号中未定义任何内容(例如user_password"user_password"不同)。

假设表看起来像这样:

create table user_password
( user_id   integer constraint user_password_pk primary key
, username  varchar2(30) not null constraint user_password_username_uk unique
, password  varchar2(30) not null );

带有示例测试数据:

insert into user_password (user_id, username, password)
values (1, 'ndubizuacn', 'Kittens');

软件包的固定版本如下:

create or replace package msgg_session as

    procedure authenticate
        ( username_to_auth in user_password.username%type
        , password_to_use  in user_password.password%type );

    function get_user_id
        return user_password.user_id%type;

end msgg_session;
/

create or replace package body msgg_session as

    priv_number user_password.user_id%type;

    procedure authenticate
        ( username_to_auth in user_password.username%type
        , password_to_use  in user_password.password%type )
    is
    begin
        select user_id into priv_number
        from   user_password
        where  lower(username) = lower(username_to_auth)
        and    password = password_to_use;

    exception
        when no_data_found then
            raise_application_error(-20000, 'Not authenticated');
    end authenticate;


    function authenticated_user
        return varchar2
    is
    begin
        return null;
    end authenticated_user;


    function get_user_id
        return user_password.user_id%type
    is
    begin
        return priv_number;
    end get_user_id;

end msgg_session;
/

测试:

begin
    msgg_session.authenticate('ndubizuacn', 'Kittens');
    dbms_output.put_line(msgg_session.get_user_id);
end;
/

假设启用dbms_output,这将打印值1

使用类似这样的全局变量并不能创建一个很好的界面,但这是分配的要求,所以我想它显示了如何使用它。同样需要拨打两次电话-也许您可以扩展authenticated_user函数以提供备用接口(传递用户名和密码,一次取回user_id)。

以纯文本格式存储密码存在明显的安全风险,有时会说您永远都不要使用任何可以忘记密码的在线服务(如果您忘记密码,这些天这种情况很少见,但是它曾经很常见)。完全不存储密码而是存储ora_hash(upper(username)||'~'||password))会更安全,例如,对于用户名ndubizuacn和密码Kittens,您将存储2160931220。然后,您的身份验证功能可能类似于:

function authenticated_user
    ( username_to_auth in user_password.username%type
    , password_to_use  in user_password.password%type )
    return user_password.user_id%type
is
    l_user_id user_password.user_id%type;
begin
    select user_id into l_user_id
    from   user_password
    where  username = username_to_auth
    and    password_hash = ora_hash(upper(username_to_auth)||'~'||password_to_use);

    return l_user_id;
exception
    when no_data_found then
        raise_application_error(-20000, 'Not authenticated');
end authenticated_user;