O web2py oferece aos seus usuários um eficiente e customizável sistema de controle de acesso baseado no modelo RBAC – Role Base Access Control, que permite restringir o acesso ao sistema à apenas usuários devidamente registrados e autorizados.
O modelo RBAC é uma alternativa ao modelo MAC (Mandatory Access Control) e DAC (Discretionary Access Control), ele trabalha com regras (roles) e permissões (permissions). As roles funcionando como grupos, aos quais iremos associar os usuários e as permissions serão utilizadas para determinar o que os grupos e seus usuários poderão realizar. Ou seja, as permissões não serão associadas diretamente aos usuários, mas serão transmitidas quando os usuários forem associados às roles (grupos ou regras). No modelo RBAC, as permissões são associadas à determinadas operações, assim como em um modelo de Organização, já as ACLs utilizadas nos sistemas baseados em DAC controlam as permissões à nível dos objetos.
No web2py a classe que implementa o modelo RBAC é a Auth
; para ativar o funcionamento dos mecanismos de autenticação, o web2py precisa definir algumas tabelas (auth_tables
), no banco de dados da aplicação, de forma que seja possível gerenciar todas as regras, permissões e usuários.
Auth Tables:
O funcionando do sistema de controle de acesso do web2py, precisa adicionar as seguintes tabelas o banco de dados da aplicação:
auth_user
: esta tabela conterá os dados básicos dos usuários, tais como: nome, e-mail, senha e status; sendo que este último campo pode assumir os seguintes valores:registration pending
(quando o usuário ainda não foi autorizado),accepted
( quando registro foi realizado com sucesso) eblocked
(quando usuário está bloqueado e não pode acessar a aplicação).auth_group
: armazena as informações sobre os gupos, ou as regras (roles), em uma estrutura de relacionamento de muitos para muitos (m-to-m); pois um usuário pode pertencer à vários grupos e um grupo pode estar associado à vários usuários. Os grupos poderão ser identificados tanto pelo seu ID, quanto pela sua role (o nome dado ao grupo).auth_membership
: esta tabela estabelece o vinculo dos usuários com os grupos, permitindo que a estrutura de relacionamento muitos para muitos seja normalizada.auth_permission
: relaciona os grupos (roles) com as permissões; que são identificadas por um nome, que podem ser o de uma tabela do banco; sendo que este campo pode assumir qualquer um dos valores válidos em web2pyauth_event
: registra as alterações ocorridas nas demais tabelas, e os acessos realizados viaCRUD
.auth_cas
: utilizado peloCAS
– Central Authentication Service, ou, simplesmente, serviço de autenticação centralizado.
Estas tabelas, listadas acima, e suas ligações podem ser representadas conforme a
Na estrutura utilizada no RBAC do web2py, as únicas restrições para a definição dos nomes das regras (roles) e das permissões, são as mesmas válidas pra as demais definições do web2py.
Características do RBAC
Uma vez que um usuário tenha sido adicionado à estrutura do RBAC, o web2py provê uma API que permite determinar se ele está conectado (logged), se ele é membro de um determinado grupo e se este lhe fornece um dado privilégio (permissão).
Além disto, o web2py possui uma funcionalidade denominada decorators
, que pode ser utilizada para determinar quais usuários poderão ter acesso, ou utilizar, determinadas funções. Por exemplo, podemos definir que apenas os usuários “logados” poderão ter acesso à função; ou somente usuários associados à um determinado grupo; ou se o usuário possui uma determinada permissão. Esta funcionalidade evita que determinadas actions
sejam utilizadas por quaisquer usuários. Os decorators
devem ser inseridos imediatamente antes da definição da função a qual ele deve ser aplicado.
Além das permissões que podemos adicionar a estrutura do RBAC, o web2py vem configurado para reconhecer e utilizar algumas classes de permissão que estão diretamente ligadas aos métodos do CRUD
; ou seja as permissões: create
, read
, update
e delete
.
Autenticação
Por meio do processo de autenticação, os usuários serão identificados na estrutura do RBAC do web2py. A classe Auth
suporta vários métodos de autenticação, sendo que o método default consiste na autenticação local baseada na tabela auth_user
; dentre os outros sistemas suportados destacam-se: Google, PAM, LDAP, Facebook, LinkedIn, Dropbox, OpenID e OAuth.
Para utilizarmos a classe Auth
precisamos adicionar as linhas, listadas a seguir, em um dos arquivos de modelo (models
), de preferência aquele utilizado para a definição do banco de dados e de suas tabelas.
from gluon.tools import Auth auth=Auth(db) auth.define_tables ( )
Dentro da pasta models
da aplicação localize o arquivo db.py
, que por padrão começa com linhas:
# -*- coding: utf-8 -*- # ------------------------------------------------------------------------- # AppConfig configuration made easy. Look inside private/appconfig.ini # Auth is for authenticaiton and access control # ------------------------------------------------------------------------- from gluon.contrib.appconfig import AppConfig from gluon.tools import Auth
Perceba que alinha destacada é aquela que realiza a importação do módulo Auth
, que depois será utilizado para instanciar um objeto da classe com o mesmo nome. Descendo mais um pouco, nas linhas do arquivo, encontraremos:
# host names must be a list of allowed host names (glob syntax allowed) auth = Auth(db, host_names=configuration.get('host.names')) # ------------------------------------------------------------------------- # create all tables needed by auth, maybe add a list of extra fields # ------------------------------------------------------------------------- auth.settings.extra_fields['auth_user'] = [] auth.define_tables(username=False, signature=False)
Na primeira linha destacada, estamos instanciando o objeto auth
da classe Auth
, neste exemplo, estamos utilizando um segundo argumento que estudaremos em outro momento. Na segunda linha destacada, temos o comando utilizado para criar/atualizar as tabelas utilizadas pelo RBAC.
A classe Auth
, por padrão, utiliza o endereço de e-mail, dos usuários para autentica-los (username=False
), mas podemos alterar este padrão, de forma que possamos utilizar o seu username, ou login name.
auth.define_tables (username=True)
Quando várias aplicações se autenticam, utilizando a mesma base de dados é importante desabilitar o processo de migração. O processo de migração consiste na atualização física do banco de dados, baseada nas definições dos arquivos de modelo, neste exemplo é o arquivo db.py
.
auth.define_tables (username=True, migrate=False)
Para tornar os métodos de autenticação, da classe Auth
, disponíveis, devemos adicionar algumas linhas de código em uma controle, localizada na subpasta controllers
.
def user ( ) : return dict (form=auth())
Neste exemplo utilizaremos o arquivo default.py
, que já deve conter algo semelhante à:
# ---- Action for login/register/etc (required for auth) ----- def user(): """ exposes: http://..../[app]/default/user/login http://..../[app]/default/user/logout http://..../[app]/default/user/register http://..../[app]/default/user/profile http://..../[app]/default/user/retrieve_password http://..../[app]/default/user/change_password http://..../[app]/default/user/bulk_register use @auth.requires_login() @auth.requires_membership('group name') @auth.requires_permission('read','table name',record_id) to decorate functions that need access control also notice there is http://..../[app]/appadmin/manage/auth to allow administrator to manage users """ return dict(form=auth())
Podemos acessar esta função, utilizando uma view
modelo denominada user.html
, que geralmente é fornecida pelo web2py e que deve estar disponível no seguinte subpasta, da aplicação views/default
. Dependendo o valor passado, via request.args(0)
, ou seja via argumento, para o formulário gerado pela função user
, a controller
pode expor várias actions
, as quais podem ser acessadas por meio da URL:
http://[host]/[appname]/default/user/[argumento]
Segue a lista e a finalidade das actions que podem ser expostas pela função:
register (default/user/register)
: permite que novos usuários se registrem. O web2py, nos permite habilitar o uso do CAPTCHA no processo de registro, ele também fornece uma ferramenta que calcula a entropia da senha, que é definida no arquivoweb2py.js
, localizado na subpastastatic/js
. Para melhor a qualidade das senhas, podemos utilizar, um outro recurso fornecido pelo web2py, o validadorIS_STRONG
, que ajuda a prevenir que sejam aceitas senhas fracas. Estaaction
gera uma tela semelhante à Figura 2: Registro de Usuários
login (default/user/login)
: permite que os usuários registrados se conectem ao sistema.
logout (default/user/logout)
: desconecta o usuário atual e retorna a página anteriormente carregada.profile (default/user/profile)
: permite ao usuário “logado” editar o seu profile (perfil). A tabela com os dados de perfil do usuário não possui uma estrutura fixa, ou seja, ela pode ser customizada de acordo com a necessidade da aplicação. O processo necessário para customização da tabelaauth_user
será apresentado em outro momento.
change_password (default/user/change_password)
: permite ao usuário alterar sua senha.
verify_email (default/user/verify_email)
: quando a verificação de e-mail está habilitada, sempre que um usuário se registra, ele recebe um e-mail de verificação, cujo conteúdo possui um link que direciona para estaaction
.retrieve_username (default/user/retrieve_username)
: quando utilizamos o login name, ou username, em vez do endereço de e-mail, no processo de autenticação, podemos usar este método para permitir ao usuário recuperar seu username, basta o usuário confirmar o endereço de fornecido durante o cadastro.
request_reset_password (default/user/retrieve_username)
: permite aos usuários que esqueceram a sua senha, solicitar um nova. O usuário receberá um e-mail com um link que aponta para oaction
reset_password
.
impersonate (default/user/impersonate)
: permite a um usuário assumir a “personalidade” de outro, mas somente se o usuário conectado possuir os privilégios necessários. Para determinar se o usuário possui os privilégios necessário podemos utilizar o comando:
has_permission (“impersonate”, db.auth_user, user_id)
groups (default/user/groups)
: apresenta a lista de grupos aos quais o usuário, atualmente conectado, está associado. O conteúdo gerado pelaaction
dependerá das configurações de cada aplicação, na Figura 9 temos o conteúdo de uma tela de exemplo.
not_authorized (default/user/not_authorized)
: quando o usuário tenta realizar algo que ele não está autorizado, estaaction
é utilizada para apresenta uma mensagem de erro.navbar (default/user/navbar)
: é uma funçãohelper
que gera uma barra (bar) com os links para asactions
delogin/register/etc
.
Por padrão, todas as actions
, listadas anteriormente, serão expostas quando utilizados o método apresentado; mas podemos restringir o acesso à apenas algumas delas. Neste caso, precisamos associar cada uma à uma função específica. Podemos, por exemplo, utilizar o código abaixo para expor apenas as actions
de login, de registro e de perfil.
def logar ( ) : return dict ( form=auth.login ( ) ) def registar ( ) : return dict ( form=auth.register ( ) ) def perfil ( ) : return dict ( form=auth.profile ( ) )
Utilizando os decorators
, podemos restringir o acesso as funções, como por exemplo, aos usuários registrados e logados (autenticados) :
@auth.requires_login () def perfil ( ) : return dict ( form=auth.profile ( ) )
auth.user e auth.user_groups
O elemento auth.user
contem uma cópia do registro db.auth_user
, relacionado ao usuário atualmente conectado, ou None
caso não tenha ocorrido o processo de autenticação. Ainda associado ao usuário logado, temos o auth.user_id
, que contem o ID do usuário, que originalmente está armazenado no campo db.auth_user.id
.
Além das informações básicas sobre o usuário conectado, temos o dicionário auth.user_groups
, onde suas chaves (keys
) são os IDs dos grupos nos quais o usuário está associado.
Restringindo o processo de registro
O web2py permite que qualquer usuário se registre no RBAC da aplicação, mas também nos permite impedir que o usuário se conecte até que um dos administradores aprove o seu cadastro; para isto, devemos ajustar o valor associado ao elemento auth.settings.registration_requires_approval
, geralmente definido no arquivo db.py
. Como podemos observar o valor padrão para esta configuração é False
:
auth.settings.registration_requires_approval = False
Para ativar o procedimento de aprovação devemos alterar o valor o elemento para True
auth.settings.registration_requires_approval = True
O registro pode ser aprovado via appadmin
ou via programação. Os registros pendentes possuem o campo registration_key
configurados com o valor pending
, o registro será aprovado quando seu valor for alterado para vazio, ou seja, eu conteúdo for limpo. Para bloquear o acesso de um determinado usuário à aplicação, devemos alterar o valor, deste campo, para disabled
ou blocked
.
Ainda podemos impedir que um novo usuário possa acessar o formulário de registro, neste caso devemos adicionar a seguinte linha de configuração ao arquivo db.py
.
auth.settings.actions_disabled.append('register')
Com isto finalizamos nossa breve introdução sobre o modelo RBAC
implementado pelo web2py, nos próximos artigos abordaremos mais sobre um pouco sobre este modelo e algumas de suas funcionalidades.