Devise
Last updated
Was this helpful?
Last updated
Was this helpful?
Não é novidade que os serviços de autenticação são cruciais para praticamente todos os websites modernos, principalmente para garantir o armazenamento dos dados de usuários ou limitar funcionalidades apenas a usuários autorizados.
No caso do rails, existem diversas gems que nos possibilitam o desenvolvimento de sistemas com autenticação, sendo o a gem mais utilizada entre elas (mais de 400 mil usuários).
Como não trabalhamos com rails full-stack, para manter a referência do usuário e mantê-lo sempre logado iremos utilizar um token de autenticação, que será uma chave única passada no cabeçalho de todas as requisições, informando à api qual é o usuário que está logado.
Para isso, faremos o uso da gem , que foi feita para funcionar com o devise e irá facilitar bastante essa parte de autenticação por token.
Assim como a maioria das gems, para começar a utilizar o devise, devemos adicioná-la ao nosso projeto, adicionando a linha gem 'devise'
na Gemfile e rodando o comando bundle
no diretório do projeto.
Em seguida, rode o comando rails g devise:install
para instalar todos os arquivos do devise. Com o isso o devise já estará pronto para ser usado.
Além disso, como iremos realizar a autenticação por token, também precisaremos adicionar gem 'simple_token_authentication'
à gemfile e rodar o bundle.
Iremos utilizar o devise para criarmos models de usuário que necessitem de autenticação, podendo ser uma model de cliente, de administrador, de moderador ou qualquer outra que nossa aplicação precise.
Nesse tutorial, criaremos apenas uma model de usuário genérica User, mas é importante ressaltar que esse é apenas o nome de model que será utilizado nesse exemplo. Caso a sua model tenha outro nome, substitua, onde aparecer, a palavra user pelo nome de sua model.
Para criar a model com o devise, é como criar uma model normal, porém agora substituindo a palavra chave model por devise no comando:
Esse comando irá criar a model User, que já terá automaticamente o campo email. Repare que a model não tem o campo de senha, apenas o campo encrypted_password, isso é para garantir que não seja possível visualizar a senha dos usuários que forem cadastrados em nossa aplicação.
Em seguida, podemos gerar uma migration nova para adicionar os campos que desejamos que o usuário tenha, como nome e idade, por exemplo.
Agora a tabela de usuário já deve estar em seu banco de dados, e já é possível criar uma instância de usuário dentro do console do rails, em que precisamos passar, além dos campos criados na migration acima, o email, senha e confirmação de senha do usuário, sendo que a senha deve ter no mínimo 6 caracteres.
Pronto, criamos nossa primeira instância da model de usuário, mas agora como fazer para descobrir se ele foi criado com a senha correta se não conseguimos ver isso na model? Para isso, podemos chamar o método valid_password?, que retornará true se a senha passada for a senha da model e false caso contrario.
Para a parte de autenticação por token, é necessário entrar no arquivo da model (models/user.rb) e adicionar a linha acts_as_token_authenticatable
. Além disso, é necessário adicionar um campo na model para armazenar o token, que queremos que seja único e com o tamanho máximo de 30 caracteres, para isso iremos gerar uma nova migration.
Agora todos os usuários que forem sendo criados já terão um token atrelados e, caso já tenha criado algum usuário sem o token de authenticação, não é necessário excluí-lo de seu banco de dados, basta dar um update nas instâncias que ainda não possuem o token que ele será gerado automaticamente.
Com a model já criada, podemos criar uma controller versionada de usuários com rails g controller api::v1::users
e dentro da controller vamos criar duas requisições básicas: login e logout.
Para a função de login, devemos receber como parâmetro o email e a senha do usuário que está querendo logar e, caso encontremos um usuário com aquele email e a senha esteja correta, retorne um json com os dados do usuário.
Para a função de logout, é preciso que o usuário esteja logado anteriormente e usaremos o token de autenticação para esse efeito. Para isso, adicionamos na primeira linha da controller acts_as_token_authentication_handler_for User, only: :logout
, que fará com que antes de ser executado o método de logout, seja verificado se o token e o email recebidos do cabeçalho são válidos para alguma instância da model de usuário.
Perceba que com essa verificação antes do método, sempre que uma autenticação por token falhar, o rails será redirecionado para sua página inicial, que muitas vezes não é o comportamento desejado. Para evitar isso podemos simplesmente adicionar ao final dessa linha, fallback_to_devise: false
, no entanto, o recomendado é criarmos um método próprio para lidar com essa falha na autenticação, em que podemos simplesmente renderizar uma mensagem de erro.
Em seguida, precisamos adicionar esse método nas rotas, então entre no arquivo routes.rb e adicione a linha
Como o rails não carrega essa pasta automaticamente, devemos entrar no arquivo config/application.rb e adicionar a linha abaixo:
Por fim, entre no arquivo config/initializers/devise.rb, procure pela parte do Warden que é o que faz a parte de login e adicione a linha abaixo para sobrescrever o método de falha com o seu método customizado
Agora já podemos fazer o nosso método de logout, que irá simplesmente apagar o token de autenticação do usuário atual
Ao fazer uma requisição, seja pelo insomnia ou pelo react mesmo, temos a opção de passar um header para a requisição, em que iremos passar o email e o token do usuário que está logado. Para isso, vamos supor que eu fiz o login de um usuário com email exemplo@gmail.com e token de autenticação abcd1234. Com essas informações, entraremos no insomnia (ou thunder client, se preferir) e criaremos uma nova requisição (Ctrl + N) para o método de logout, que será um post, com a rota criada para a requisição, nesse exemplo será http://localhost:3000/logout. Agora abra a aba Header e adicione as linhas
Agora já será possível testar o método de logout, ou qualquer outra requisição que precise de um usuário logado para funcionar.
Após criarmos as requisições na controller, precisamos definir as rotas. Para isso, entre no arquivo routes.rb e perceba que lá tem a linha devise_for :users
, que define as rotas padrões do devise, que não precisaremos utilizar, mas que não podemos simplesmente apagar das rotas. Portanto, para não termos conflitos, modificamos essa linha para indicar que o usuário ainda vai ter os métodos do devise, porém as rotas não serão criadas.
Agora já podemos criar as rotas normalmente
Em seguida, iremos criar uma classe customizada para sobrescrever o método de redirecionamento da url de acordo com o tutorial da própria . Para criar essa classe, iremos criar no diretório lib o arquivo CustomFailure.rb e definimos a classe com