サーバー側で画像ファイルを受け取る際に正しい画像データかチェックします。
こちらの記事(ホワイトハッカーへの道 二歩目)を参考にすると以下をする必要があります。
- ファイル名にパスが含まれていないかチェックする。
- ファイルにスクリプトタグが含まれていないかのチェックする。
- MIMEタイプに対応する拡張子をチェックする。
- アップロードサイズをチェックする。
- アップロード時にEXIFは削除する。
- アップロードされたファイル名をランダムなファイル名にする。
- アップロードディレクトリ、ファイルは実行権限を付与しない。
- アップロード先をドキュメントルート外フォルダかクラウドにする。
ここでは3つ目のMIMEタイプのチェックを行う独自バリデーションのコードを書きます。
package aaaaaa.validator;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Documented
@Constraint(validatedBy = MediaTypeImageValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MediaTypeImage {
String message() default "{MediaTypeImage.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
package aaaaaa.validator;
import java.util.Arrays;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.io.FilenameUtils;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
public class MediaTypeImageValidator implements ConstraintValidator<MediaTypeImage, MultipartFile> {
@Override
public boolean isValid(MultipartFile value, ConstraintValidatorContext context) {
// Emptyなら通す。他のバリデーターで検証する
if (value.isEmpty()) {
return true;
}
// メディアタイプ
MediaType mediaType = MediaType.parseMediaType(value.getContentType());
// 拡張子
String ext = FilenameUtils.getExtension(value.getOriginalFilename());
List<MediaType> mediaTypeList = Arrays.asList(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG, MediaType.IMAGE_GIF);
List<String> extList = Arrays.asList("jpg", "jpeg", "png", "gif");
// メディアタイプと拡張子をチェック
return mediaTypeList.stream().anyMatch((mType) -> mediaType.includes(mType))
&& extList.stream().anyMatch((v) -> ext.toLowerCase().equals(v));
}
}
ファイル拡張子もチェックしたけど必要ないかもしれない。
以下のように使う。
package aaaaaa.dto.form;
import org.springframework.web.multipart.MultipartFile;
import aaaaaa.validator.ContentTypeZip;
import aaaaaa.validator.MediaTypeImage;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class UploadForm {
@MediaTypeImage
private MultipartFile thumbnail;
}
他はコードを掘り返してるんだけど、記憶が曖昧で……。とりあえずここまで。