防止注入

master
lion 24 hours ago
parent 0dfbd013e2
commit c72bec50ec

@ -2,7 +2,9 @@
namespace App\Http\Controllers\Admin;
use App\Helpers\ResponseCode;
use App\Models\AppointmentType;
use Illuminate\Support\Facades\Validator;
class AppointmentTypeController extends BaseController
{
@ -83,6 +85,41 @@ class AppointmentTypeController extends BaseController
*/
public function save()
{
$all = request()->all();
$messages = [
'name.required' => '类型名称必填',
'name.max' => '类型名称不能超过100字',
];
$validator = Validator::make($all, [
'id' => 'nullable|integer',
'name' => ['required', 'string', 'max:100', function ($attribute, $value, $fail) {
if (preg_match('/(select|insert|update|delete|pg_sleep|union|\/\*|\*\/|--|sleep\s*\()/i', $value)) {
$fail('名称包含非法字符');
}
}],
'introduce' => 'nullable|string|max:500',
'start_time' => ['nullable', 'regex:/^\d{2}:\d{2}$/'],
'end_time' => ['nullable', 'regex:/^\d{2}:\d{2}$/'],
'is_show' => 'nullable|in:0,1',
'is_book' => 'nullable|in:0,1',
'sort' => 'nullable|integer',
'total' => 'nullable|integer|min:0',
'floor' => 'nullable|string|max:50',
'image_id' => 'nullable|array',
'image_id.*' => 'integer',
'content' => 'nullable|string',
'tips' => 'nullable|string',
], $messages);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$allowed = [
'id', 'name', 'introduce', 'start_time', 'end_time', 'is_show', 'is_book',
'sort', 'total', 'floor', 'image_id', 'content', 'tips',
];
request()->replace(array_intersect_key($all, array_flip($allowed)));
return parent::save();
}

@ -40,8 +40,8 @@ class OtherController extends CommonController
$query->where('appointment_type_id', $all['appointment_type_id']);
}
})->where('show_front', 1)->get();
// 场地类型
$appointment_type = AppointmentType::get();
// 场地类型(仅返回小程序展示的有效数据)
$appointment_type = AppointmentType::where('is_show', 1)->orderBy('sort')->get();
// 获取开放手机号的课程体系
$course_types_open_mobile = CourseType::where('open_mobile', 1)->get();
return $this->success(compact('config', 'appointment', 'appointment_type', 'course_types_open_mobile'));

@ -15,8 +15,11 @@ class AppointmentConfig extends SoftDeletesModel
public function getFilesAttribute($value)
{
if (empty($this->file_ids)) return [];
return Upload::whereIn('id', $this->file_ids)->get();
$ids = AppointmentType::normalizeJsonIdList($this->file_ids);
if (empty($ids)) {
return [];
}
return Upload::whereIn('id', $ids)->get();
}
/**

@ -6,14 +6,40 @@ namespace App\Models;
class AppointmentType extends SoftDeletesModel
{
protected $fillable = [
'admin_id', 'department_id', 'name', 'image_id', 'introduce',
'start_time', 'end_time', 'is_book', 'is_show', 'sort', 'content',
'tips', 'total', 'floor',
];
protected $casts = ['image_id' => 'json'];
protected $appends = ['image'];
public function getImageAttribute($value)
{
if (empty($this->image_id)) return [];
return Upload::whereIn('id', $this->image_id)->get();
$ids = self::normalizeJsonIdList($this->image_id);
if (empty($ids)) {
return [];
}
return Upload::whereIn('id', $ids)->get();
}
/** 兼容 image_id 为单值、数组或脏数据的情况 */
public static function normalizeJsonIdList($value): array
{
if ($value === null || $value === '' || $value === []) {
return [];
}
if (is_array($value)) {
return array_values(array_filter($value, function ($id) {
return $id !== null && $id !== '' && is_numeric($id);
}));
}
if (is_numeric($value)) {
return [(int) $value];
}
return [];
}
public function image()

Loading…
Cancel
Save