Profile no Oracle 19c: senha, bloqueio e sessões
Profile no Oracle 19c: a senha que vence em 180 dias no DEFAULT, o ORA-28000 por senha errada, a função de complexidade e o limite de sessões (ORA-02391).

O banco foi criado, a aplicação subiu, tudo funcionou por meses. Um dia o sistema para de conectar e o log mostra que a senha do usuário da aplicação expirou. Ninguém configurou isso de propósito: o usuário foi criado sem profile, caiu no DEFAULT, e no DEFAULT do Oracle 19c a senha vale 180 dias.
O profile é o lugar onde o Oracle guarda as regras de senha e os limites de recurso de cada usuário. Montei os cenários no Oracle 19c multitenant do lab, e as saídas abaixo são as que ele devolveu.
O que é um profile no Oracle
Um profile é um conjunto nomeado de limites. Todo usuário tem exatamente um, e quem não recebe nenhum no CREATE USER fica com o DEFAULT. Os limites se dividem em dois tipos, que aparecem na coluna RESOURCE_TYPE da DBA_PROFILES:
| Tipo | O que controla | Exemplos | Quando vale |
|---|---|---|---|
| PASSWORD | política de senha | FAILED_LOGIN_ATTEMPTS, PASSWORD_LIFE_TIME, PASSWORD_VERIFY_FUNCTION | sempre |
| KERNEL | recursos da sessão | SESSIONS_PER_USER, IDLE_TIME, CPU_PER_CALL | só com RESOURCE_LIMIT = TRUE |
O profile não concede nada. Privilégio vem de GRANT, e o profile só limita o que o usuário pode fazer com a conta e com a sessão.
O profile DEFAULT e a senha de 180 dias
No lab, conectado como SYSDBA na PDB HUMAN_RESOURCES do CDB1:
select profile, resource_name, resource_type, limit
from dba_profiles
where profile = 'DEFAULT'
order by resource_type, resource_name;
PROFILE RESOURCE_NAME RESOURCE_TYPE LIMIT
--------- -------------------------- ------------- ----------
DEFAULT COMPOSITE_LIMIT KERNEL UNLIMITED
DEFAULT CONNECT_TIME KERNEL UNLIMITED
(...)
DEFAULT SESSIONS_PER_USER KERNEL UNLIMITED
DEFAULT FAILED_LOGIN_ATTEMPTS PASSWORD 10
DEFAULT INACTIVE_ACCOUNT_TIME PASSWORD UNLIMITED
DEFAULT PASSWORD_GRACE_TIME PASSWORD 7
DEFAULT PASSWORD_LIFE_TIME PASSWORD 180
DEFAULT PASSWORD_LOCK_TIME PASSWORD 1
DEFAULT PASSWORD_REUSE_MAX PASSWORD UNLIMITED
DEFAULT PASSWORD_REUSE_TIME PASSWORD UNLIMITED
DEFAULT PASSWORD_VERIFY_FUNCTION PASSWORD NULL
17 rows selected.
Todos os limites de recurso vêm UNLIMITED. Na parte de senha, dois valores pegam muita gente: 10 tentativas erradas bloqueiam a conta, e a senha expira em 180 dias, com mais 7 de tolerância. Depois disso o usuário precisa trocar a senha para conectar. Se ele é o usuário da aplicação, a aplicação para.
Já perdi a conta de quantas vezes vi isso acontecer. Por isso, para usuário de serviço de aplicação, eu deixo a PASSWORD_LIFE_TIME como UNLIMITED num profile próprio, e uso validade de senha nos usuários de pessoas.
O roteiro completo com todos os comandos está em https://mrdba.com.br/labs/profiles-oracle?utm_source=blog&utm_medium=artigo&utm_campaign=profiles-oracle, pronto para rodar no seu ambiente.
Criando um profile de senha
Eu crio um profile por tipo de usuário: aplicação, desenvolvedores, BI, consultor externo. No lab, um profile com política de senha mais rígida:
create profile prf_app_hr limit
failed_login_attempts 3
password_lock_time 1
password_life_time 90
password_grace_time 7
password_reuse_time 365
password_reuse_max 5
inactive_account_time 30;
create user hr_seg
identified by "SenhaForte#2026"
default tablespace users
temporary tablespace temp
quota 100M on users
profile prf_app_hr;
grant create session to hr_seg;
A DBA_USERS mostra o profile de cada usuário:
select username, profile, account_status
from dba_users
where username = 'HR_SEG';
USERNAME PROFILE ACCOUNT_STATUS
---------- ------------ --------------
HR_SEG PRF_APP_HR OPEN
ORA-28000: a conta bloqueada por senha errada
Com FAILED_LOGIN_ATTEMPTS 3, três senhas erradas bastam. Depois disso, nem a senha certa entra:
$ sqlplus hr_seg/"senha_errada"@//oplanodba:1521/HUMAN_RESOURCES
ORA-01017: invalid username/password; logon denied
(mais duas vezes)
$ sqlplus hr_seg/"SenhaForte#2026"@//oplanodba:1521/HUMAN_RESOURCES
ORA-28000: The account is locked.
A conta fica em LOCKED(TIMED) e destrava sozinha depois do PASSWORD_LOCK_TIME, que aqui é 1 dia. O DBA pode destravar antes:
alter user hr_seg account unlock;
É a defesa básica contra tentativa de senha por força bruta. Em conta de serviço eu não uso valor muito baixo, porque uma aplicação mal configurada repetindo a senha antiga trava a própria conta.
Senha expirada e PASSWORD_GRACE_TIME
A PASSWORD_LIFE_TIME define a validade. A PASSWORD_GRACE_TIME é o prazo extra, em que o login ainda funciona com aviso de que a senha vai expirar. Funciona como um cheque especial: terminado o prazo, a troca vira obrigatória.
Para ver o comportamento sem esperar 90 dias, dá para forçar:
alter user hr_seg password expire;
A DBA_USERS passa a mostrar EXPIRED, e no próximo login o SQL*Plus pede a senha nova:
$ sqlplus hr_seg/"SenhaForte#2026"@//oplanodba:1521/HUMAN_RESOURCES
ORA-28001: the password has expired
Changing password for hr_seg
New password:
Retype new password:
Password changed
No dia a dia isso é raro, e em usuário de aplicação é perigoso: quem conecta é um programa, que não sabe responder ao pedido de troca.
Complexidade de senha com ORA12C_VERIFY_FUNCTION
Por padrão o Oracle aceita qualquer senha. A PASSWORD_VERIFY_FUNCTION liga uma função que valida a senha no CREATE USER e em cada troca. O 19c já traz três prontas:
select object_name
from dba_objects
where owner = 'SYS'
and object_type = 'FUNCTION'
and object_name like 'ORA12C%VERIFY%'
order by object_name;
OBJECT_NAME
--------------------------------
ORA12C_STIG_VERIFY_FUNCTION
ORA12C_STRONG_VERIFY_FUNCTION
ORA12C_VERIFY_FUNCTION
Ligando a função só no profile do lab:
alter profile prf_app_hr limit
password_verify_function ora12c_verify_function;
alter user hr_seg identified by senha1;
ORA-28003: password verification for the specified password failed
ORA-20000: password length less than 8 bytes
Uma senha com maiúscula, minúscula, número e tamanho suficiente passa. Se a empresa tem uma política própria, dá para escrever uma função sua e ligar no profile do mesmo jeito.
Um cuidado: o script utlpwdmg.sql, que aparece em muito tutorial, recria essas funções e também altera o profile DEFAULT. A regra passa a valer para todos os usuários da PDB. As funções já existem no 19c, então não precisa dele.
Limite de sessões: ORA-02391
Os limites KERNEL dependem do parâmetro RESOURCE_LIMIT. No 19c o padrão já é TRUE, e no lab ele estava assim. Na PDB SALES_HISTORY do CDB2:
create profile prf_sh_recursos limit
sessions_per_user 2
connect_time 120
idle_time 15
cpu_per_call 6000
logical_reads_per_session unlimited
composite_limit unlimited;
create user sh_lab
identified by "SenhaForte#2026"
default tablespace users
temporary tablespace temp
quota 50M on users
profile prf_sh_recursos;
grant create session to sh_lab;
Duas sessões do SH_LAB em terminais separados conectam. A terceira é recusada:
ORA-02391: exceeded simultaneous SESSIONS_PER_USER limit
Eu uso bastante esse limite para usuário de BI e consultor externo, que às vezes abre um monte de conexões ao mesmo tempo. Não é a forma mais fina de controlar consumo, mas resolve o caso comum.
Alterando, trocando e removendo profiles
Um ALTER PROFILE muda o limite para todos os usuários do profile, e um ALTER USER troca o profile de um usuário sem recriá-lo:
alter profile prf_sh_recursos limit
sessions_per_user 3
idle_time 30;
alter user sh_lab profile default;
Para remover um profile que ainda tem usuários, o Oracle exige o CASCADE:
drop profile prf_app_hr;
ORA-02382: profile PRF_APP_HR has users assigned, cannot drop without CASCADE
Com drop profile prf_app_hr cascade, os usuários não são apagados: voltam para o DEFAULT. Mesmo assim eu prefiro consultar a DBA_USERS antes, mover cada usuário para o profile certo e só então dropar. Voltar para o DEFAULT significa voltar para a senha de 180 dias.
Profile comum no CDB
Tudo acima foi dentro de PDBs, onde o profile é local. No CDB$ROOT dá para criar um profile comum, com a mesma regra de nome dos usuários comuns, vista no artigo sobre criar usuários no Oracle: prefixo C## e CONTAINER = ALL.
create profile c##prf_corp limit
failed_login_attempts 5
password_life_time 60
container = all;
A CDB_PROFILES confirmou o C##PRF_CORP com os dois limites nos quatro containers abertos do CDB2 (CON_ID 1, 3, 4 e 5).
Boas práticas com profiles
Não deixe usuário de aplicação no DEFAULT. Crie profiles por finalidade, decida a validade de senha de cada um e documente qual sistema usa qual profile.
Ligue a função de complexidade logo na criação do banco. Num banco que roda há anos é bem mais difícil, porque a troca de política precisa de apoio da empresa inteira. Começando do zero, ela entra sem resistência.
Em CDB, decida cedo se o profile é local em cada PDB ou comum no root.
O próximo vídeo da série trata de privilégios de sistema, o lado do GRANT que o profile não cobre. Se você está montando a base para trabalhar como DBA, o e-book Raízes de um DBA organiza esse caminho: https://mrdba.com.br/roteiro-dba.
Marcio Mandarino
DBA Oracle e SQL Server há mais de 20 anos. Atendo plantão, recuperação de incidente e gestão contínua de bancos de dados. Este artigo saiu de um laboratório que rodou antes de virar texto.

