mar 132015
 

Recebemos uma questionamento interessante.

Como não permitir que o usuário mude sua própria senha ?

Confesso que isso é um pouco estranho, mas dependendo de como a aplicação foi feita pode fazer sentido.

Pode parecer brincadeira, mas já vi casos onde o time de aplicação alterou a senha do usuário de banco em pleno horário comercial ! Foi sem querer ? Achavam que estavam em desenvolvimento ? Seja qual for a razão, tivemos sérios impactos.

Por que então não trocar a senha e não deixar ninguém saber ? Talvez como nesse caso, para trocar a senha você precise fazer um deploy da aplicação e pode ser que não se tenha os recursos necessários para faze-los, … pode ser que hajam outros motivos…
Sendo assim, a opção de não permitir o usuário trocar a própria senha pode parecer interessante.

É obvio que num ambiente totalmente controlado, onde a senha seria criptografada e nunca acessível ao time de aplicação, isso dificilmente seria necessário.

Mas sempre gosto de aprender, então acho que vale a pena ler o post, mesmo que não seja esse o seu caso…

Vamos lá, temos a principio duas alternativas:

  • Uso de trigger
  • Uso de password_function do profile

Conhece alguma outra opção ? Envie uma mensagem que posso complementar o post.

Vamos começar falando da primeira opção , o uso de trigger.

Vamos criar uma trigger que será acionada em alteração de objetos da database.
Isso quer dizer que vamos ter problemas com “Alter table” por exemplo ?

Para que você consiga manipular essas informações na trigger, existem vários atributos que podem ser usados para identificar se estamos falando de um alter table ou de um alter user por exemplo.
No nosso caso, vamos usar o atributo ORA_DICT_OBJ_TYPE.

Em um alter table ele traria o valor TABLE, já em um alter user o valor desse atributo seria USER.

Mas e o que dizer do nome usuário ? Você pode usar o atributo ora_login_user.
Lembrando que o atributo ora_login_users traz o usuário logado. O usuário que esta sendo alterado é o o ora_dict_obj_name.

Como assim ?
Se você rodar o seguinte comando como sys:

Alter user cauduro identified by oracle.

    
SQL> show user 
USER is "SYS" 
SQL> Alter user cauduro identified by oracle replace oracle;

O atributo ora_login_user vai trazer sys e o ora_dict_obj_name vai trazer cauduro.

Se voce rodar o seguinte comando como cauduro:

    
    SQL> show user 
    USER is "CAUDURO" 
    SQL> Alter user cauduro identified by oracle replace oracle; 

O atributo ora_login_user e ora_dict_obj_name vai trazer cauduro.

Como provavelmente seu objetivo não é bloquear alterações pelo sys, eu estou usando o atributo ora_login_user.

A trigger ficaria assim:

    
create or replace trigger alter_trigger_objects
 before alter
 on database
 declare
   l_usuario_sem_permissao varchar2(15);
 begin
   l_usuario_sem_permissao := 'CAUDURO';
 if     (ora_dict_obj_type = 'USER')  -- SE FOR UMA ALTERACAO DE USUARIO 
    and (ora_login_user = l_usuario_sem_permissao)  -- SE FOR UMA ALTERACAO REALIZADA PELO USUARIO l_usuario_sem_permissao
    and (ora_dict_obj_name = l_usuario_sem_permissao)  -- E SE ELE ESTIVER ALTERANDO ELE MESMO 
    then
        raise_application_error(-20099,'Voce nao pode alterar sua senha, contate o administrador');
 end if;
 end;
 /
 

Ela funciona mesmo ?
Vejamos na prática.

    
SQL> show user
USER is "SYS"
SQL> alter user cauduro identified by oracle replace oracle;

User altered.

SQL> connect cauduro/oracle
Connected.
SQL> show user
USER is "CAUDURO"
SQL> alter user cauduro identified by oracle replace oracle;
alter user cauduro identified by oracle replace oracle
                                 *
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-20099: Voce nao pode alterar sua senha, contate o administrador
ORA-06512: at line 9

Como vocês viram, não foi possível trocar a senha, fácil não é ?

Vamos falar agora sobre a segunda opção, o uso da password function.

O conceito aqui é simples, vamos alterar o profile do usuário para usar uma função que sempre vai dar erro na troca de senha, ou seja, é impossivel ele colocar uma senha nova, pois ela nunca atenderá os requisitos da função de verificação de senha.

Basicamente configuro assim o ambiente:


CREATE OR REPLACE FUNCTION verify_pwd_false
(username varchar2,
password varchar2,
old_password varchar2)
RETURN boolean IS 
BEGIN 
   if upper(SYS_CONTEXT('USERENV','AUTHENTICATED_IDENTITY')) = 'CAUDURO' then
       raise_application_error(-20099,'Voce nao pode alterar sua senha, contate o administrador');
   end if;
return true;
END;
/

CREATE PROFILE no_password_change LIMIT PASSWORD_VERIFY_FUNCTION verify_pwd_false;

ALTER USER CAUDURO PROFILE no_password_change;

Vamos ver na prática:

   
SQL> show user
USER is "SYS"

SQL> alter user cauduro identified by oracle replace oracle;

User altered.

SQL> connect cauduro/oracle
Connected.
SQL> show user
USER is "CAUDURO"

SQL> alter user cauduro identified by oracle replace oracle;
alter user cauduro identified by oracle replace oracle
*
ERROR at line 1:
ORA-28003: password verification for the specified password failed
ORA-20099: Voce nao pode alterar sua senha, contate o administrador

 

As duas opções funcionam.

Qual você prefere ?

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)