BOARD 게시물을 작성한 USER 또는 ADMIN 권한을 가진 경우 게시글을 수정, 삭제 할 수 있도록 기능을 구현하라는 조건이 있었다.
ADMIN만 권한을 갖거나 게시물을 작성한 USER에게만 권한을 갖도록 구현하는것은 어렵지 않은데 두가지 조건을 다 충족시키는것이 고민이되었다.
처음에는 WebSecurityConfig 파일에서
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf((csrf) -> csrf.disable());
// 기본 설정인 Session 방식은 사용하지 않고 JWT 방식을 사용하기 위한 설정
http.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);
http.authorizeHttpRequests((authorizeHttpRequests) ->
authorizeHttpRequests
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources 접근 허용 설정
.requestMatchers("/").permitAll() // 메인 페이지 요청 허가
.requestMatchers("/signup").permitAll()
.requestMatchers("/signin").permitAll()
.requestMatchers(HttpMethod.PUT, "/boards/**").hasAnyAuthority(UserRoleEnum.Authority.ADMIN, UserRoleEnum.Authority.USER)
.anyRequest().authenticated() // 그 외 모든 요청 인증처리
);
.requestMatchers(HttpMethod.PUT, "/boards/**").hasAnyAuthority(UserRoleEnum.Authority.ADMIN, UserRoleEnum.Authority.USER)
위의 코드를 추가하면 되지 않을까 생각했다.뒤에 USER는 서비스에서 ID값을 비교하는 구문을 추가해주면 모든 USER가 아니라 게시글을 작성한 USER가 걸러질줄 알았지만 테스트한 결과 ADMIN도 권한이 없다는 에러가 나왔다.
두번째로 생각한것이
@PreAuthorize("hasAnyRole('ADMIN','USER')")
조건이 필요한 기능마다 컨트롤러에서 메서드위에 어노테이션을 붙여주는것이였다. 그럼 똑같이 USER가 모든 USER가 아닌 게시글의 작성자 ID와 동일한 경우 해당 USER만 권한을 가질것이라 생각했지만 이 어노테이션도 ADMIN조차 권한이 부여되지않았다.
그래서 마지막으로 생각한것이 Service에서 현재 로그인되어있는 유저의 role이 admin인 경우, 게시글 작성자의 id과 현재 로그인되어있는 유저의 id 값을 비교해서 권한을 주도록 하였다.
@Transactional
public BoardResponseDto updateBoard(BoardRequestDto boardRequestDto, Long userId, Long id) {
User user = userRepository.findById(userId).orElseThrow(() ->
new EntityNotFoundException("존재하지않는 유저입니다.")
);
Board board = boardRepository.findById(id).orElseThrow(() ->
new EntityNotFoundException("존재하지않는 보드입니다.")
);
if (UserRoleEnum.ADMIN.equals(user.getRole())) {
board.update(boardRequestDto);
return new BoardResponseDto(board);
}
if (userId != board.getUser().getId()) {
throw new EntityNotFoundException("보드를 수정 할 수 있는 권한이 없습니다.");
}
board.update(boardRequestDto);
return new BoardResponseDto(board);
}