4
respostas

[Dúvida] Como validar se usuário da requisição é o mesmo do token

Estou com uma Duvida sobre como implementar mais segurança na aplicação e adicionar uma validação se o usuário que esta fazendo a requisição é o dono das informações. Nas aulas a aprendemos a gerar um token para um usuário e que para cada requisição é preciso informar esse token, porém é possível chamar requisições com informações de outros usuários passando esse token.

Como posso estar validando se o usuário que vem no token é o mesmo usuário que retorna/envio na requisição?

Com isso poderia evitar que o o usuario1 consiga obter, alterar ou deletar informações do usuario2. Pensei em aplicar um filtro, mas pelo que entendi nas aulas ele é chamado antes da requisição, pensei em criar um método para realizar essa validação, onde eu buscaria a informação no header, pegaria o usuário que vem no token e compararia com o ID do usuário que foi enviado na requisição, e esse método poderia ser reutilizado nas demais requisições, mas não sei como fazer isso. Posso estar reutilizando algum método aplicado nas aulas? Seria uma boa pratica?

Qual seria as boas praticas ou a possível solução para esse problema?

4 respostas

Oi Humberto!

Dentro do token foi inserido os dados do usuário ao qual o token foi gerado (no curso foi adicionado o id como subject, mas é possível adicionar mais informações)

Mas se esse token "vazar", ou seja, outra pessoa tiver acesso a ele, vai poder disparar requisições se passando pelo usuário dono do token. Infelizmente não tem como evitar isso, sendo que no máximo é possível dificultar, por exemplo utilizando o protocolo HTTPS para evitar que alguém que intercepte as requisições tenha acesso aos tokens.

Quanto a evitar que um usuário altere informações de outro usuário, isso é possível e tranquilo de se fazer. Por exemplo, imagine que no projeto do curso somente o usuário que cadastrou um médico possa o alterar/excluir. Você precisaria salvar na tabela de médicos o id do usuário que criou o registro:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "responsavel_id")
private Usuario responsavel;

E no controller consegue injetar nos métodos o usuário disparando a requisição:

@DeleteMapping("/{id}")
@Transactional
public ResponseEntity excluir(@PathVariable Long id, @AuthenticationPrincipal Usuario logado) {
    ...
}

E bastaria checar se o usuário logado é o mesmo usuário setado no médico. Algo como:

if (logado.equals(medico.getResponsavel())) {
    //pode excluir...
}

Bons estudos!

Entendi Rodrigo, nesse cenário essa validação funcionaria, mas em outro cenário por exemplo:

Uma aplicação de cadastro de usuário, um usuário pode se cadastrar, ver o seus dados, altera-los e exclui-los. O usuário faz o login e a aplicação gera o token, com isso eu consigo criar um método que valida se o usuário presente no token é o mesmo que vem na resposta da requisição e aplico esse método na chamada de GET, PUTe DELETE , como é uma validação que farei para todas as chamadas poderia criar um filtro, que antes de fazer a chamada verifica se o ID na URI e o mesmo do token.

   @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        request.getRequestURI();

Aqui eu eu consigo receber a URI da request "usuario/5" , como buscar esse ID dentro dessa String, talvez utilizar um regex? não sei kk

Qual seria a melhor solução aplicar um filtro e fazer essa validação, ou criar um método que faz essa validação e aplicar nas controllers?

Eu poderia passar o id do usuario que vem no token direto na requisição? COmo eu faria isso?

Até daria para fazer via filter, mas o código ia ficar meio complicado, pois teria que ficar checando se a url é uma url que você deseja fazer a validação de segurança, além de extrair o id da url e fazer a lógica de validação.

Eu prefiro fazer isso numa classe service mesmo, pois fica mais explicita essa validação e fica mais fácil de escrever um testes automatizado, embora seja um código que vai se repetir. Dá para extrair essa validação numa classe e fazer as services que precisarem a chamar também.