2. CSRF token & Javascript, csrf toke ajax (ok)
https://viblo.asia/p/tap-15-csrf-laravel-07LKXBGrlV4
Ví dụ 0: Đọc ví dụ https://c-i-ph-n-m-m-tr-n-ubuntu-c-n-thi.gitbook.io/project/delete-record-using-ajax-request-in-laravel-example-ok
Sử dụng ajax và truyền token vào data
$(".deleteRecord").click(function(){
var id = $(this).data("id");
var token = $("meta[name='csrf-token']").attr("content");
$.ajax(
{
url: "users/"+id,
type: 'DELETE',
data: {
"id": id,
"_token": token,
},
success: function (){
console.log("it Works");
}
});
});
Ví dụ 1:
C:\xampp\htdocs\reset\resources\views\products.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Laravel 5 - Multiple delete records with checkbox example</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-confirmation/1.0.5/bootstrap-confirmation.min.js"></script>
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
<div class="container">
<h3>Laravel 5 - Multiple delete records with checkbox example</h3>
<button style="margin-bottom: 10px" class="btn btn-primary delete_all" data-url="{{ url('myproductsDeleteAll') }}">Delete All Selected</button>
<table class="table table-bordered">
<tr>
<th width="50px"><input type="checkbox" id="master"></th>
<th width="80px">No</th>
<th>Product Name</th>
<th>Product Details</th>
<th width="100px">Action</th>
</tr>
@if($products->count())
@foreach($products as $key => $product)
<tr id="tr_{{$product->id}}">
<td><input type="checkbox" class="sub_chk" data-id="{{$product->id}}"></td>
<td>{{ ++$key }}</td>
<td>{{ $product->name }}</td>
<td>{{ $product->details }}</td>
<td>
<a href="{{ url('myproducts',$product->id) }}" class="btn btn-danger btn-sm"
data-tr="tr_{{$product->id}}"
data-toggle="confirmation"
data-btn-ok-label="Delete" data-btn-ok-icon="fa fa-remove"
data-btn-ok-class="btn btn-sm btn-danger"
data-btn-cancel-label="Cancel"
data-btn-cancel-icon="fa fa-chevron-circle-left"
data-btn-cancel-class="btn btn-sm btn-default"
data-title="Are you sure you want to delete ?"
data-placement="left" data-singleton="true">
Delete
</a>
</td>
</tr>
@endforeach
@endif
</table>
</div> <!-- container / end -->
</body>
<script type="text/javascript">
$(document).ready(function () {
$('#master').on('click', function(e) {
if($(this).is(':checked',true))
{
$(".sub_chk").prop('checked', true);
} else {
$(".sub_chk").prop('checked',false);
}
});
$('.delete_all').on('click', function(e) {
var allVals = [];
$(".sub_chk:checked").each(function() {
allVals.push($(this).attr('data-id'));
});
if(allVals.length <=0)
{
alert("Please select row.");
} else {
var check = confirm("Are you sure you want to delete this row?");
if(check == true){
var join_selected_values = allVals.join(",");
$.ajax({
url: $(this).data('url'),
type: 'DELETE',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
data: 'ids='+join_selected_values,
success: function (data) {
if (data['success']) {
$(".sub_chk:checked").each(function() {
$(this).parents("tr").remove();
});
alert(data['success']);
} else if (data['error']) {
alert(data['error']);
} else {
alert('Whoops Something went wrong!!');
}
},
error: function (data) {
alert(data.responseText);
}
});
$.each(allVals, function( index, value ) {
$('table tr').filter("[data-row-id='" + value + "']").remove();
});
}
}
});
$('[data-toggle=confirmation]').confirmation({
rootSelector: '[data-toggle=confirmation]',
onConfirm: function (event, element) {
element.trigger('confirm');
}
});
$(document).on('confirm', function (e) {
var ele = e.target;
e.preventDefault();
$.ajax({
url: ele.href,
type: 'DELETE',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
success: function (data) {
if (data['success']) {
$("#" + data['tr']).slideUp("slow");
alert(data['success']);
} else if (data['error']) {
alert(data['error']);
} else {
alert('Whoops Something went wrong!!');
}
},
error: function (data) {
alert(data.responseText);
}
});
return false;
});
});
</script>
</html>
C:\xampp\htdocs\reset\routes\web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\ProductController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', [HomeController::class, 'index'])->name('home');
Route::get('myproducts', [ProductController::class, 'index']);
Route::delete('myproducts/{id}', [ProductController::class, 'destroy']);
Route::delete('myproductsDeleteAll', [ProductController::class, 'deleteAll']);
C:\xampp\htdocs\reset\app\Http\Controllers\ProductController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
class ProductController extends Controller {
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index() {
$products = DB::table("products")->get();
return view('products', compact('products'));
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
DB::table("products")->delete($id);
return response()->json(['success' => "Product Deleted successfully.", 'tr' => 'tr_' . $id]);
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function deleteAll(Request $request) {
$ids = $request->ids;
$idsa = explode(",", $ids);
DB::table("products")->whereIn('id', $idsa)->delete();
return response()->json(['success' => "Products Deleted successfully."]);
}
}
Ví dụ 2:
1. CSRF token & Javascript
Theo mặc định thì file resources/js/bootstrap.js
sẽ lấy token từ thẻ meta
với name csrf-token
để đăng ký cho thư viện Axios HTTP. Lúc này mọi request đều được gửi cùng với token.
/**
* Next we will register the CSRF Token as a common header with Axios so that
* all outgoing HTTP requests automatically have it attached. This is just
* a simple convenience so we don't have to attach every token manually.
*/
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
Nếu bạn không sử dụng thư viện này, bạn phải cấu hình thủ công. Chẳng hạn nếu bạn sử dụng thư viện Ajax jQuery thay cho Axios HTTP thì có thể làm như sau:
Đầu tiên tạo thẻ meta
với name là csrf-token
trong thẻ head
.
<meta name="csrf-token" content="{{ csrf_token() }}">
Tiếp đó chỉ việc đăng ký ở file JS:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Như vậy, mỗi lần gửi request với ajax, bạn đã kèm theo token csrf rồi đấy.
Để kiểm chứng bạn có thể tạo một blade view home
với nội dung sau:
<html>
<head>
<title>CSRF Laravel</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
<form action="/post" method="POST">
<input type="submit" value="Send">
</form>
<script src="https://code.jquery.com/jquery.min.js"></script>
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('form').submit(function(e) {
e.preventDefault();
$.ajax({
url: '/post',
type: 'POST',
success: function(res) {
console.log(res);
}
});
});
</script>
</body>
</html>
Trong đoạn code trên mình đã khai báo thẻ meta chứa token csrf ở thẻ head
. Sau đó tạo một form HTML, nhưng không khai báo thẻ @csrf
đển tạo input token. Về Javascript, mình import thư việc jQuery, thực hiện setup như ở trên rồi thực thi gửi request với ajax đơn giản.
Để test thì chúng ta đăng ký các route sau:
Route::get('/', function () {
return view('home');
});
Route::post('/post', function () {
return 'Posted';
});
Đây là kết quả sau khi submit form:
Last updated