add XSS content filter to DTOs

This commit is contained in:
2026-04-20 10:45:45 -06:00
parent b380681be3
commit a10841dd02
9 changed files with 51 additions and 0 deletions

View File

@@ -1,10 +1,12 @@
package com.petshop.backend.dto.category; package com.petshop.backend.dto.category;
import com.petshop.backend.util.SafeContent;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import java.util.Objects; import java.util.Objects;
public class CategoryRequest { public class CategoryRequest {
@NotBlank(message = "Category name is required") @NotBlank(message = "Category name is required")
@SafeContent
private String categoryName; private String categoryName;
private String categoryType; private String categoryType;

View File

@@ -1,5 +1,6 @@
package com.petshop.backend.dto.pet; package com.petshop.backend.dto.pet;
import com.petshop.backend.util.SafeContent;
import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@@ -11,6 +12,7 @@ import java.util.Objects;
public class PetRequest { public class PetRequest {
@NotBlank(message = "Pet name is required") @NotBlank(message = "Pet name is required")
@SafeContent
private String petName; private String petName;
@NotBlank(message = "Species is required") @NotBlank(message = "Species is required")

View File

@@ -1,5 +1,6 @@
package com.petshop.backend.dto.product; package com.petshop.backend.dto.product;
import com.petshop.backend.util.SafeContent;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.Positive;
@@ -8,11 +9,13 @@ import java.util.Objects;
public class ProductRequest { public class ProductRequest {
@NotBlank(message = "Product name is required") @NotBlank(message = "Product name is required")
@SafeContent
private String prodName; private String prodName;
@NotNull(message = "Category ID is required") @NotNull(message = "Category ID is required")
private Long categoryId; private Long categoryId;
@SafeContent
private String prodDesc; private String prodDesc;
@NotNull(message = "Product price is required") @NotNull(message = "Product price is required")

View File

@@ -1,5 +1,6 @@
package com.petshop.backend.dto.service; package com.petshop.backend.dto.service;
import com.petshop.backend.util.SafeContent;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.Positive;
@@ -10,8 +11,10 @@ import java.util.Set;
public class ServiceRequest { public class ServiceRequest {
@NotBlank(message = "Service name is required") @NotBlank(message = "Service name is required")
@SafeContent
private String serviceName; private String serviceName;
@SafeContent
private String serviceDesc; private String serviceDesc;
@NotNull(message = "Service price is required") @NotNull(message = "Service price is required")

View File

@@ -1,11 +1,13 @@
package com.petshop.backend.dto.store; package com.petshop.backend.dto.store;
import com.petshop.backend.util.SafeContent;
import jakarta.validation.constraints.Email; import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import java.util.Objects; import java.util.Objects;
public class StoreRequest { public class StoreRequest {
@NotBlank(message = "Store name is required") @NotBlank(message = "Store name is required")
@SafeContent
private String storeName; private String storeName;
@NotBlank(message = "Address is required") @NotBlank(message = "Address is required")

View File

@@ -1,5 +1,6 @@
package com.petshop.backend.dto.supplier; package com.petshop.backend.dto.supplier;
import com.petshop.backend.util.SafeContent;
import jakarta.validation.constraints.Email; import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import java.util.Objects; import java.util.Objects;

View File

@@ -1,5 +1,6 @@
package com.petshop.backend.dto.user; package com.petshop.backend.dto.user;
import com.petshop.backend.util.SafeContent;
import com.petshop.backend.entity.User; import com.petshop.backend.entity.User;
import jakarta.validation.constraints.Email; import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
@@ -15,10 +16,12 @@ public class UserRequest {
private String password; private String password;
@NotBlank(message = "First name is required") @NotBlank(message = "First name is required")
@SafeContent
@Size(max = 50) @Size(max = 50)
private String firstName; private String firstName;
@NotBlank(message = "Last name is required") @NotBlank(message = "Last name is required")
@SafeContent
@Size(max = 50) @Size(max = 50)
private String lastName; private String lastName;

View File

@@ -0,0 +1,17 @@
package com.petshop.backend.util;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = SafeContentValidator.class)
public @interface SafeContent {
String message() default "Content contains prohibited characters or scripts";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@@ -0,0 +1,18 @@
package com.petshop.backend.util;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;
public class SafeContentValidator implements ConstraintValidator<SafeContent, String> {
private static final Pattern DANGEROUS = Pattern.compile(
"<script|</script|javascript:|on\\w+\\s*=|<iframe|<object|<embed|<form|<input|<img[^>]+on\\w+",
Pattern.CASE_INSENSITIVE);
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null || value.isBlank()) return true;
return !DANGEROUS.matcher(value).find();
}
}