0

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

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

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

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;

  /
4

1 回答 1

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启用,这将打印 value 1

对这样的事情使用全局变量并不是一个很好的界面,但这是赋值的要求,所以我想它展示了如何使用一个。需要进行两次调用也是如此 - 也许您可以扩展您的authenticated_user功能以提供替代接口(传入用户和密码,一次性取回 user_id)。

以纯文本形式存储密码是一种明显的安全风险,有时人们会说,如果您忘记密码,您永远不应该使用任何可以向您发送密码的在线服务(这些天您不会经常看到这种情况,但它曾经很常见)。根本不存储密码而是存储会更安全ora_hash(upper(username)||'~'||password)),例如,您将存储用户名ndubizuacn和密码。那么您的身份验证功能可能类似于:Kittens2160931220

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;
于 2019-09-22T10:15:20.060 回答