Операция DELETE возвращает ОШИБКУ: произошла непредвиденная ошибка (тип = Запрещено, статус = 403). Запрещенный

Я работаю над проектом весенний ботинок, который включает лист тимьяна, пружинная безопасность. Он отлично работает, когда я выполняю - показ списка продуктов, отображение сведений о продуктах, добавление нового продукта, обновление существующего продукта.

Но когда я выполняю удаление продукта, выдает следующую ОШИБКУ:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Jul 18 16:59:16 BDT 2019

There was an unexpected error (type=Forbidden, status=403).

Forbidden

Вот мой код:

product_list.html

<!DOCTYPE html>
<html xmlns:th = "http://www.thymeleaf.org">
    <head>
        <title>Product List</title>
        <link rel = "stylesheet" th:href = "@{/css/bootstrap.css}">
    </head>
    <body>
        <div class = "container">
            <h1>Product List</h1>
            <hr>
            <a class = "btn btn-success" th:href = "@{/products/add}">Create New Product</a>
            <hr>
            <table class = "table">
                <thead>
                    <tr>
                        <th>Product ID</th>
                        <th>Name</th>
                        <th>Brand</th>
                        <th>Made In</th>
                        <th>Price</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                    <tr th:each = "theProduct:${theProducts}">
                        <td th:text = "${theProduct.id}">Product ID</td>
                        <td th:text = "${theProduct.name}">Name</td>
                        <td th:text = "${theProduct.brand}">Brand</td>
                        <td th:text = "${theProduct.madein}">Made In</td>
                        <td th:text = "${theProduct.price}">Price</td>
                        <td>
                            <a class = "btn btn-info" th:href = "@{'/products/show/' + ${theProduct.id}}">View</a>
                            <a class = "btn btn-warning" th:href = "@{'/products/edit/' + ${theProduct.id}}">Edit</a>
                            <a class = "btn btn-danger" th:data-the-product-id = "${theProduct.id}" data-toggle = "modal" data-target = "#deleteConfirmationModal">Delete</a>
                            
                            <div class = "modal fade" id = "deleteConfirmationModal" tabindex = "-1" role = "dialog" aria-labelledby = "deleteConfirmationModalLabel" aria-hidden = "true">
                              <div class = "modal-dialog" role = "document">
                                <div class = "modal-content">
                                  <div class = "modal-header">
                                    <h5 class = "modal-title" id = "exampleModalLabel">Delete Confirmation</h5>
                                    <button type = "button" class = "close" data-dismiss = "modal" aria-label = "Close">
                                      <span aria-hidden = "true">&times;</span>
                                    </button>
                                  </div>
                                  <div class = "modal-body">
                                    Are you sure you want to DELETE the Product.
                                    <br>
                                    <form id = "deleteForm" action = "#" th:method = "DELETE">
                                        <button type = "submit" class = "btn btn-danger">Delete Employee</button>
                                    </form>
                                  </div>
                                  <div class = "modal-footer">
                                    <button type = "button" class = "btn btn-secondary" data-dismiss = "modal">Close</button>
                                  </div>
                                </div>
                              </div>
                            </div>
                            
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
        <script th:src = "@{/js/jquery-3.3.1.js}"></script>
        <script th:src = "@{/js/popper.js}"></script>
        <script th:src = "@{/js/bootstrap.js}"></script>
        <script>
        $('#deleteConfirmationModal').on('show.bs.modal', function (event) {
            var anchorLink = $(event.relatedTarget)
            var theProductId = anchorLink.data('theProductId')
            var modal = $(this)
            $("#deleteForm").attr("action", "/products/delete/" + theProductId)
        })
    </script>
    </body>
</html>

Продуктконтроллер.java

package com.example.demo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.demo.dao.ProductRepository;
import com.example.demo.entity.Product;

@Controller
@RequestMapping("/products")
public class ProductController {
    
    @Autowired
    private ProductRepository productRepository;
    
    @GetMapping("/index")
    public String index(Model theModel) {
        List<Product> theProducts = productRepository.findAll();
        theModel.addAttribute("theProducts", theProducts);
        return "product/product_list";
    }
    
    @GetMapping("/add")
    public String add(Model theModel) {
        Product theProduct = new Product();
        theModel.addAttribute("theProduct", theProduct);
        return "product/product_add_form";
    }

    @GetMapping("/show/{productId}")
    public String show(@PathVariable int productId, Model theModel) {
        Product theProduct = productRepository.findById(productId).get();
        if (theProduct == null) {
            return null;
        }
        theModel.addAttribute("theProduct", theProduct);
        return "product/product_detail";
    }
    
    @PostMapping("/create")
    public String create(@ModelAttribute("theProduct") Product theProduct) {
        theProduct.setId(0);
        productRepository.save(theProduct);
        return "redirect:/products/index";
    }

    @GetMapping("/edit/{productId}")
    public String edit(@PathVariable(name = "productId") int productId, Model theModel) {
        Product theProduct = productRepository.findById(productId).get();
        theModel.addAttribute("theProduct", theProduct);
        return "product/product_edit_form";
    }

    @PutMapping("/update")
    public String update(@ModelAttribute("theProduct") Product theProduct) {
        productRepository.save(theProduct);
        return "redirect:/products/index";
    }
    
    @DeleteMapping("/delete/{productId}")
    public String delete(@PathVariable int productId) {
        Product tempProduct = productRepository.findById(productId).get();
        if (tempProduct == null) {
            return null;
        }
        productRepository.deleteById(productId);
        return "redirect:/products/index";
    }
}

Логинконтроллер.java

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LoginController {
    
    @RequestMapping("/login")
    public String login() {
        return "login"; 
    }
    
    @GetMapping("/")
    public String home(Model theModel) {    
        return "redirect:/products/index";  
    }
}

SecurityConfig.java

package com.example.demo.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        UserBuilder users = User.withDefaultPasswordEncoder();
        auth.inMemoryAuthentication().withUser(users.username("admin").password("Admin.123").roles("EMPLOYEE", "ADMIN"));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {  
        http.authorizeRequests()
            .antMatchers("/css/**")
            .permitAll()
            .antMatchers("/js/**")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/authenticateTheUser")
            .permitAll()
            .and()
            .logout()
            .permitAll();
    }
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
2 388
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Попробуйте отключить токен csrf в вашей конфигурации:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**")
                .permitAll()
                .antMatchers("/js/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/authenticateTheUser")
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and().csrf().disable();
    }

вы правы... я проверяю его код... но csrf очень важен из соображений безопасности.... даже для целей тестирования

Istiaque Hossain 18.07.2019 18:16

Я полагаю, проблема в том, что вы пропустили th:href для кнопки удаления.

Ответ принят как подходящий

к счастью, вы добавляете «модальный» внутри тимелеафа в каждом цикле, поэтому отредактируйте свой html в соответствии с моим кодом....

 <form id = "deleteForm" th:action = "${'/products/delete/' + theProductId}" th:method = "DELETE">
         <button type = "submit" class = "btn btn-danger">Delete Employee</button>
 </form>

это проверенный код...работает нормально..
вы просто пропустите «th: action», потому что он не работает как форма тимьяна. поэтому тимелеаф не предоставляет скрытое поле «_csrf»;

Спасибо, это сработало. На самом деле я добавил th:action = "${'/products/delete/' + theProductId}" в начале. Но я сделал что-то не так в JavaScript и удалил th:action. А потом решил проблему с JavaScript, но забыл добавить th:action :p

Partho63 20.07.2019 08:27

Другие вопросы по теме