I'm a beginner working on a team project and currently creating a "board" page in React + Spring Boot.
I'm really confused because I keep getting a 401 Unauthorized error when submitting a POST request to create a board with multipart/form-data.
- If I include a file, everything works fine.
- If I submit without a file, I get
401 INVALID_ACCESS_TOKENfrom the backend.
I'm new to both Spring Security and like everything, and I'm working in a team, so I want to make this work properly for all cases.
Has anyone faced a similar issue or can explain why a multipart request without files might cause a JWT to fail authentication?
controller:
@PostMapping("/create")
public ResponseEntity<?> createBoard(
@PathVariable("crewId") Long crewId,
@RequestPart("title") String title,
@RequestPart("content") String content,
@RequestParam(value = "crewBoardFile", required = false) List<MultipartFile> crewBoardFile,
@AuthenticationPrincipal MyUserDetails userDetails
) throws IOException {
CrewBoardDto crewBoardDto = new CrewBoardDto();
crewBoardDto.setTitle(title);
crewBoardDto.setContent(content);
crewBoardDto.setCrewBoardFile(crewBoardFile);
Long loginUserId = userDetails.getMemberId();
CrewBoardDto createBoard = crewBoardService.createBoard(crewId, crewBoardDto, loginUserId, crewBoardFile);
return ResponseEntity.ok(createBoard);
}
service:
@Override
public CrewBoardDto createBoard(Long crewId, CrewBoardDto crewBoardDto, Long loginUserId, List<MultipartFile> crewBoardFile) throws IOException {
CrewEntity crewEntity = crewRepository.findById(crewId)
.orElseThrow(() -> new IllegalArgumentException("x"));
MemberEntity memberEntity = memberRepository.findById(loginUserId)
.orElseThrow(() -> new IllegalArgumentException("x"));
crewRepository.findByIdAndCrewMemberEntities_MemberEntity_Id(crewId, loginUserId)
.orElseThrow(() -> new IllegalArgumentException("x"));
crewBoardDto.setMemberId(memberEntity.getId());
crewBoardDto.setCrewId(crewId);
CrewBoardEntity crewBoardEntity = CrewBoardEntity.toCrewBoardEntity(crewBoardDto);
CrewBoardEntity savedBoard = null;
crewBoardFile = crewBoardDto.getCrewBoardFile();
if (crewBoardFile == null || crewBoardFile.isEmpty() || crewBoardFile.get(0).isEmpty()) {
savedBoard = crewBoardRepository.save(crewBoardEntity);
} else {
List<CrewBoardImageEntity> savedImages = new ArrayList<>();
// for (MultipartFile file : crewBoardDto.getCrewBoardFile()) {
// if (file != null && !file.isEmpty()) {
// String originalFileName = file.getOriginalFilename();
// String newFileName = awsS3Service.uploadFile(file);
// CrewBoardImageEntity boardImageEntity = CrewBoardImageEntity.toCrewBoardImageEntity(crewBoardEntity2, originalFileName, newFileName);
// crewBoardImageRepository.save(boardImageEntity);
// crewBoardRepository.save(crewBoardEntity);
// }
// }
for (MultipartFile boardFile : crewBoardFile) {
if (boardFile != null && !boardFile.isEmpty()) {
UUID uuid = UUID.randomUUID();
String originalFileName = boardFile.getOriginalFilename();
String newFileName = uuid + "_" + originalFileName;
String filePath = "E:/full/upload/" + newFileName;
File file = new File(filePath);
boardFile.transferTo(file);
CrewBoardImageEntity boardImageEntity = CrewBoardImageEntity.toCrewBoardImageEntity(crewBoardEntity, originalFileName, newFileName);
CrewBoardImageEntity savedImage = crewBoardImageRepository.save(boardImageEntity);
savedImages.add(savedImage);
}
}
crewBoardEntity.setCrewBoardImageEntities(savedImages);
savedBoard = crewBoardRepository.save(crewBoardEntity);
}
return CrewBoardDto.toDto(savedBoard);
}
react: