Solucionado (ver solução)
Solucionado
(ver solução)
20
respostas

HTTP Status 403 – Forbidden

Ao preencher os campos com os dados de usuário e senha (da forma feita na aula) sou recebido com o seguinte erro:

HTTP Status 403 – Forbidden
Type Status Report

Message Acesso negado

Description The server understood the request but refuses to authorize it.

Apache Tomcat/9.0.37

Tal erro não ocorre quando "driblo" a autenticação com o acréscimo da barra ao final do endereço na URL assim como está descrito na classe SecurityConfiguration:

package br.com.casadocodigo.loja.conf;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.web.filter.CharacterEncodingFilter;

import br.com.casadocodigo.loja.dao.UsuarioDAO;

@EnableWebMvcSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UsuarioDAO usuarioDao;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests() 
            .antMatchers("/produtos/form").hasRole("ADMIN")
            .antMatchers(HttpMethod.POST, "/produtos").hasRole("ADMIN")
            .antMatchers(HttpMethod.GET, "/produtos").hasRole("ADMIN")
            .antMatchers("/produtos/**").permitAll()
            .antMatchers("/carrinho/**").permitAll()
            .antMatchers("/pagamento/**").permitAll()
            .antMatchers("/resources/**").permitAll()
            .antMatchers("/").permitAll()
            .anyRequest().authenticated()
            .and().formLogin();

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(usuarioDao)
            .passwordEncoder(new BCryptPasswordEncoder());
    }
}

Agredeço a atenção e estou a disposição para enviar mais dados caso necessário.

20 respostas

Olá Guilherme, tudo bem? Eu não entendi muito bem o problema, poderia explicar melhor? O erro acontece quando você faz o envio dos dados para o login é isso? E também não entendi muito bem essa parte de "driblar a autenticação com o acréscimo da barra ao final do endereço na URL", poderia explicar melhor isso para que eu possa ti ajudar, se puder enviar umas imagens (pode colocar no imgur e deixar os links aqui no tópico) do que está acontecendo seria útil para tentarmos identificar o problema e a solução.

Fico aguardando retorno!

Oi Jonilson, tudo bem?

Perdão pelos meus equívocos, o erro é no login e no carrinho/add, onde pelo curso vemos como fazer um sistema de autenticação, para que certas páginas estejam bloqueadas para não administradores, e foi a partir desse ponto que não consegui mais acessar as demais páginas.

Ao entrar na página home da casadocodigo não há erro algum, consigo ver os dados dos produtos cadastrados, e quando clico neles consigo acessá-los normalmente. Acredito que essas estejam funcionando como antes pelo fato de que o método configure não está bloqueando-as.

Até aí tudo bem, os dados de cadastro com usuário e senha estão no banco de dados corretamente, todo o sistema de cadastro de produtos, simulação de compra (escolha do tipo de preço, adição de itens a um carrinho de compras e finalização da compra), assim como a exibição da página com o CSS do Bootstrap estavam funcionando como apresentado nas aulas.

O problema começou apenas quando foi criada a classe SecurityConfiguration, os métodos configure que estão nela, e o restante do sistema de autenticação. Como foram vários passos dados na aula não consigo dizer exatamente o que está causando o erro para cada problema, apenas que as páginas que agoram exigem um login para serem acessadas não me permitem mais acesso mesmo com o login correto.

Para testar a autenticação eu acesso a mesma página que o instrutor:

http://localhost:8080/casadocodigo/produtos

Que me redireciona para esse link:

http://localhost:8080/casadocodigo/login

Do modo em que o código está escrito na classe SecurityConfiguration posso deixar de fazer o login acessando esse link no lugar do anterior:

http://localhost:8080/casadocodigo/produtos/

Assim eu consigo acessar a página dos produtos e suas funcioanlidades, mas o propósito da aula era testar a autenticação e não ficar como já estava.

Ao realizar o login não ocorre erro de Bad Credentials ou qualquer outro tipo de processo que esteja me retornando para o formulário de login. Sou recebido apenas com esse erro:

HTTP Status 403 – Forbidden
Type Status Report

Message Acesso negado

Description The server understood the request but refuses to authorize it.

Apache Tomcat/9.0.37

O mesmo problema ocorre para o formulário de cadastro de produtos, onde este link apresenta o erro mencionado:

http://localhost:8080/casadocodigo/produtos/form

E este me deixa acessar normalmente, porém, acusa o mesmo erro quando clico no botão "Cadastrar":

http://localhost:8080/casadocodigo/produtos/form/

Além do mais, se clicar no botão "Comprar" ná página do item sou então recebido com esse erro:

HTTP Status 403 – Forbidden
Type Status Report

Message Expected CSRF token not found. Has your session expired?

Description The server understood the request but refuses to authorize it.

Apache Tomcat/9.0.37

Links para as imagens:

https://imgur.com/FWt5VU5

https://imgur.com/KUYjQLI

https://imgur.com/zTp60US

https://imgur.com/JUMhGcb

https://imgur.com/vIMTNgR

https://imgur.com/CqeFb9G

https://imgur.com/WcPDPD8

Agradeço novamente a atenção e estou a disposição para mandar mais informações!

Agora entendi corretamente, bem realmente existe esse problema da barra no final mesmo, ele nos deixa passar, mas esse não é o problema, o problema na verdade é que a autenticação ainda não está realmente funcionando, ou então os formulário não estão com os campos CSRF. Então primeiro indico que você verifique se todos os formulários, inclusive o de Login (formulário da página de Login) estão com o campo CSRF, e me fala aqui sobre isso, porque se todos estiverem corretos o problema pode ser que o Login (a funcionalidade de autenticação) não esteja funcionando como deveria e então teremos que identificar a possível causa. Outra coisa que você já poderia fazer é adicionar o projeto no GitHub e compartilhar o link aqui pra que eu possa baixar o projeto e fazer alguns testes aqui pra ti ajudar!

Conferi os formulários via "View Page Source" e eles possuem o input CSRF do seguinte modo:

<input type="hidden" name="_csrf" value="67e8dee6-9be7-450e-94bb-56253a2d8f2c" />

Por algum motivo não estou conseguindo adicionar esse projeto em específico no GitHub, tanto pelo Eclipse como pelo Git Bash. Isso ocorre apenas com esse projeto.

Caso exista outro modo de compartilhar o projeto eu enviarei assim que possível.

Novamente obrigado pela ajuda!

Você poderia adicionar em arquivo .zip e colocar no Google drive e então compartilhar o link aqui pra eu poder acessar e verificar melhor qual é o problema!

Obrigado pela sugestão!

https://drive.google.com/file/d/1kfFWHfmv_-CqvQ5rNiYh398hPzyHQFoC/view?usp=sharing

Acho que está tudo correto, mas, caso não esteja, por favor me corrija!

Guilherme, você poderia liberar o acesso ao arquivo, quando fui tentar fazer o download tive um erro de acesso negado, muda as permissões de compartilhamento do arquivo e fala aqui pra eu tentar novamente!

Me desculpe pelo erro!

Acho que deve estar funcioando agora.

https://drive.google.com/file/d/1kfFWHfmv_-CqvQ5rNiYh398hPzyHQFoC/view?usp=sharing

Sem problemas Guilherme! Bem eu precisei faz as modificações na classe JPAConfiguration apenas para colocar um banco de dados e também usuário e senha que são diferentes, e também alterar a pasta das imagens arquivos-sumario que deu conflito com o outro projeto que eu já tinha, então dei o nome arquivos-sumario-forum como você pode ver na imagem abaixo:

Projeto no eclipse com a mudança da pasta arquivos-sumario

Mas deu tudo certo no Login, na tela abaixo usei o usuário "admin@casadocodigo.com.br" e a senha "123456":

Tela de login com usuário "admin" como passado no curso e senha 123456

Depois consegui fazer o acesso ao formulário de produtos sem nenhum problema:

Formulário de produtos funcionando corretamente

E por fim fiz o cadastro de um livro e deu certo, consegui visualizar o livro na tela de "home":

Tela de home com produto cadastrado corretamente

Então no seu caso quando aconteceu o problema, foi mostrado alguma coisa no console do Eclipse? E outra coisa você fez o cadastro do usuário com a permissão seguindo os passos do curso? Os passos são:

  • Cadastrar um Role de ADMIN:
    insert into Role values ('ROLE_ADMIN');
  • Cadastrar um usuário:
    insert into Usuario (email, nome, senha) values ('admin@casadocodigo.com.br', 'Administrador', '$2a$04$qP517gz1KNVEJUTCkUQCY.JzEoXzHFjLAhPQjrg5iP6Z/UmWjvUhq');
  • Por último, relacionar o usuário com a role da seguinte forma:
    insert into Usuario_Role(Usuario_email, roles_nome) values ('admin@casadocodigo.com.br', 'ROLE_ADMIN');

E você verificou nas tabelas no banco de dados se os dados foram salvos corretamente?

Boa noite Jonilson e muito obrigado pela resposta!

Realmente no meu banco de dados faltava inserir a relação entre o usuário e a role.

Com isso o problema de login foi completamente resolvido!

Infelizmente ainda continua o erro do CSRF Token no momento de inserir um produto no carrinho.

HTTP Status 403 – Forbidden
Type Status Report

Message Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

Description The server understood the request but refuses to authorize it.

Apache Tomcat/9.0.37

Não sei se é melhor dar como resolvido esse tópico e abrir outro ou continuar por aqui, já que o principal era o login, mas, muito obrigado pela solução!

É bem estranho mesmo, você poderia criar um novo tópico e colocar o link aqui pra eu poder responder, já que realmente é outro problema então é interessante outro tópico assim fica mais fácil para outras pessoas verificar e corrigir o problema, e esse tópico aqui você poderia marcar como solucionado!

Mas de ante mão, o problema é que não você esqueceu de adicionar um input com o CSRF, note o código abaixo que copiei diretamente do navegador:

<section class="buy-options clearfix">
  <form action='/casadocodigo/carrinho/add' method="post" class="container">
    <input type="hidden" value="1" name="produtoId" >
    <ul id="variants" class="clearfix">

        <li class="buy-option">
          <input type="radio" name="tipoPreco" class="variant-radio" id="tipoPreco" value="EBOOK" checked="checked" /> 
          <label class="variant-label" >EBOOK</label> 
          <small class="compare-at-price">R$ 39,90</small>
          <p class="variant-price">39.00</p>
        </li>

        <li class="buy-option">
          <input type="radio" name="tipoPreco" class="variant-radio" id="tipoPreco" value="IMPRESSO" checked="checked" /> 
          <label class="variant-label" >IMPRESSO</label> 
          <small class="compare-at-price">R$ 39,90</small>
          <p class="variant-price">49.00</p>
        </li>

        <li class="buy-option">
          <input type="radio" name="tipoPreco" class="variant-radio" id="tipoPreco" value="COMBO" checked="checked" /> 
          <label class="variant-label" >COMBO</label> 
          <small class="compare-at-price">R$ 39,90</small>
          <p class="variant-price">59.00</p>
        </li>

    </ul>
    <button type="submit" class="submit-image icon-basket-alt" title="Compre Agora TDD no mundo real"></button>
  </form>
</section>

E realmente não tem o campo, então a solução é você ir na página detalhe.jsp dentro da pasta produtos dentro de views e então adicionar a tag form no início do arquivo:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

E alterar a tag <form> que você está usando diretamente do HTML para a tag <form:form> do JSP e então o trecho de código deve ficar:

<section class="buy-options clearfix">
  <form:form action='<c:url value="/carrinho/add" />' method="post" cssClass="container">

    <input type="hidden" value="${produto.id}" name="produtoId" />
    <ul id="variants" class="clearfix">
      <c:forEach items="${produto.precos}" var="preco">
        <li class="buy-option">
          <input type="radio" name="tipoPreco" class="variant-radio"
            id="tipoPreco" value="${preco.tipo}" checked="checked" /> 
          <label class="variant-label">${preco.tipo}</label> 
          <small class="compare-at-price">R$ 39,90</small>
          <p class="variant-price">${preco.valor}</p>
        </li>
      </c:forEach>
    </ul>

    <button type="submit" class="submit-image icon-basket-alt" 
      title="Compre Agora ${produto.titulo}"></button>
  </form:form>
</section>

E fala se deu certo!

Fiz as alterações no detalhe.jsp e agora tenho o seguinte erro:

HTTP Status 404 ? Not Found
Type Status Report

Message The requested resource [/casadocodigo/produtos/detalhe/%3Cc:url%20value=%22/carrinho/add%22%20/%3E] is not available

Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

Apache Tomcat/9.0.37

Eu ia criar outro tópico, mas agora está dando que o curso foi desabilitado e não deixa criar mais tópicos. Não sei nem se continuará sendo útil solucionar os problemas desse projeto.

Caso não tenha necessidade de resolver esse problema eu darei o tópico como resolvido.

Mesmo assim, obrigado pelas respostas e ajuda!

Bom primeiramente vamos continuar resolvendo esses últimos problemas, já que é coisa simples, o erro aconteceu por falha minha na verdade, por causa do <c:url> que deixei no código, como você modificou para <form:form> então você precisa indicar a url do action com o s:mvcUrl ou usando o servletRelativeAction, tenta usando esse último da seguinte forma:

<section class="buy-options clearfix">
  <form:form servletRelativeAction="/carrinho/add" method="post" cssClass="container">

    <input type="hidden" value="${produto.id}" name="produtoId" />
    <ul id="variants" class="clearfix">
      <c:forEach items="${produto.precos}" var="preco">
        <li class="buy-option">
          <input type="radio" name="tipoPreco" class="variant-radio"
            id="tipoPreco" value="${preco.tipo}" checked="checked" /> 
          <label class="variant-label">${preco.tipo}</label> 
          <small class="compare-at-price">R$ 39,90</small>
          <p class="variant-price">${preco.valor}</p>
        </li>
      </c:forEach>
    </ul>

    <button type="submit" class="submit-image icon-basket-alt" 
      title="Compre Agora ${produto.titulo}"></button>
  </form:form>
</section>

E fala se deu tudo certo!

Usando o servletRelativeAction tive o seguinte erro:

HTTP Status 404 ? Not Found
Type Status Report

Message The requested resource [/casadocodigo/produtos/detalhe/4/carrinho/add] is not available

Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

Apache Tomcat/9.0.37

Que estranho isso Guilherme! Mas tenta utilizando o mvcUrl da seguinte forma:

<form:form action="${s:mvcUrl('CCC#add').build()}" method="post" cssClass="container">

    <código omitido>

</form:form>

E fala pra gente se deu certo!

Muito estranho mesmo!

Tentando com o s:mvcUrl deu o seguinte erro:

HTTP Status 404 – Not Found
Type Status Report

Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

Apache Tomcat/9.0.37

Que estranho Guilherme! Você fez a importação das tags? Como abaixo:

<%@ taglib uri="http://www.springframework.org/tags" prefix="s"%>

Porque o erro me parece apenas que ele não conseguiu interpretar o s.

Sim a importação está desse jeito mesmo.

Como só tem uma chamada desse prefixo no detalhe.jsp não sei se daria erro com outras chamadas, mas em outros jsp essa importação não indica problema. Realmente estranho!

solução!

Então faz o seguinte, deixa o form normal, usando a tag do HTML mesmo e adiciona um input csrf da seguinte forma:

<section class="buy-options clearfix">
  <form action='<c:url value="/carrinho/add" />' method="post" class="container">
    <input type="hidden" value="${produto.id }" name="produtoId" >
    <ul id="variants" class="clearfix">
      <c:forEach items="${produto.precos }" var="preco">
        <li class="buy-option">
          <input type="radio" name="tipoPreco" class="variant-radio" id="tipoPreco" value="${preco.tipo }" checked="checked" /> 
          <label class="variant-label" >${preco.tipo }</label> 
          <small class="compare-at-price">R$ 39,90</small>
          <p class="variant-price">${preco.valor }</p>
        </li>
      </c:forEach>
    </ul>
    <button type="submit" class="submit-image icon-basket-alt" title="Compre Agora ${produto.titulo }"></button>
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">
  </form>
</section>

E fala pra mim qual foi o resultado!

Muito obrigado Jonilson!

Tive que aplicar o input do csrf em todos os formulários que tinham relação com a função do carrinho (adicionar, finalizar e excluir itens).

Agora sim tudo está ocorrendo como deveria!