티스토리 뷰
안녕하세여
기존에는 메뉴를 고정적으로 사용했는데요 (유연성없이 FO에서 메뉴를 고정적으로 하드코딩함)
시큐리티에서 메뉴에 대한 접근권한을 나누다보니 사용자마다 권한에 따른 메뉴를 표기해야하는 경우가 생겼습니다
기존에 사용자마다 role이 지정되어있기 때문에
public enum UserRole {
ADMIN,
MANAGER,
DEVELOPER,
USER;
}
이 부분을 참고하여 Menu를 만들어보려고 해용
@Entity
@Table(name = "menu")
@Getter
@NoArgsConstructor
public class Menu extends BaseTimeEntity {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false, length = 255)
private String name;
@Column(nullable = true, length = 255)
private String path;
@ElementCollection(targetClass = UserRole.class, fetch = FetchType.EAGER)
@CollectionTable(name = "menu_roles", joinColumns = @JoinColumn(name = "menu_id"))
@Enumerated(EnumType.STRING)
@Column(name = "role")
private Set<UserRole> roles = new HashSet<>(); // 접근 가능한 역할 목록
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id") // 계층 구조를 위한 상위 메뉴
private Menu parent;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Menu> children = new ArrayList<>();
@Column(nullable = false)
private int menuOrder;
@Column(nullable = true)
private boolean isEnabled;
@Builder
public Menu(String name, String path, Set<UserRole> roles, Menu parent, List<Menu> children, int menuOrder, boolean isEnabled) {
this.name = name;
this.path = path;
this.roles = roles;
this.parent = parent;
this.children = children;
this.menuOrder = menuOrder;
this.isEnabled = isEnabled;
}
}
메뉴 생성까지 생각해서 빌더 어노테이션을 달아주었구요
부모메뉴, 자식메뉴가 있을 수 있어 (추후 메뉴 트리구조로 변환가능성 있음)
parent, children까지 추가해주었네요
권한은 중복값이 들어가면 안되니 HashSet으로 구현해주었답니다
테스트 개발계에 계정 여러개 중에
developer랑 administrator 를 만들어두었습니다
developer: "DEVELOPER"
administrator: "ADMIN"
의 권한을 가지고 있습니다.
Service에서 본인의 권한에 맞는 메뉴를 가지고와 Controller에게 반환해주는 작업을 했어요
(선행작업으로는 MENU를 생성하는 것이 먼저입니다 ^^*)
public List<Menu> findAllByOrderByMenuOrder(){
// 스프링 시큐리티에서 현재 인증된 사용자 정보 가져오기
Set<UserRole> currentUserRoles = getCurrentUserRoles(); // 로그인한 사용자의 역할 가져오기
// 모든 메뉴를 가져온 후, 사용자의 역할에 맞는 메뉴만 필터링
List<Menu> allMenus = menuRepository.findAllByOrderByMenuOrder();
return allMenus.stream()
.filter(menu -> menu.getRoles().stream().anyMatch(role -> currentUserRoles.contains(role)))
.collect(Collectors.toList());
}
// 현재 사용자의 권한 가져오기
public Set<UserRole> getCurrentUserRoles() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
return authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority) // 권한 문자열
.map(role -> role.replace("ROLE_", "")) // 'ROLE_' 접두사를 제거
.map(UserRole::valueOf) // 문자열을 UserRole enum으로 변환
.collect(Collectors.toSet());
}
return Set.of(); // 인증되지 않은 경우 빈 Set 반환
}
public static Set<UserRole> validateRoles(List<String> roleNames) {
Set<UserRole> validRoles = new HashSet<>();
for (String roleName : roleNames) {
try {
// UserRole Enum에 해당하는지 확인
UserRole role = UserRole.valueOf(roleName);
validRoles.add(role);
} catch (IllegalArgumentException e) {
// 유효하지 않은 역할인 경우 처리
log.error("Invalid role: " + roleName);
}
}
return validRoles;
}
menu order순으로 조회해서 반환해줘야하구 로그인(인증)된 사용자의 권한에 맞는 메뉴를 리턴해줘야하니
위와 같은 코드를 짜게 되었는데요
DB에는 enum값으로 저장이 되어있는데
User 도메인을 보면 아래와 같이 ROLE_ 이라는 접두사를 사용하고 있어요
이는 시큐리티 코드에서 메뉴별 접근권한을 나눌 때 hasRole api를 사용하고 있어서 그렇습니다.
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority("ROLE_" + userRole.name()));
}
그래서 "ROLE_" 을 ""로 치환해주는 replace함수를 넣어줬어요
이를 set객체로 반환해주고용
map함수를 통해 사용자 권한이 포함된 메뉴만 List로 반환해주는 메서드를 작성했습니다
으아아아아아아ㅏ앙아
첨에는 어떻게 해야할까 고민이 많았는데
차근차근하니 어찌저찌 해결이 되어가고 있습니다
끝..
이제 30분 쉬러갈래요...
'SpringBoot' 카테고리의 다른 글
| JWT 구조 및 Token 발급 과정 (0) | 2025.11.12 |
|---|---|
| [SpringBoot] 데이터 엑셀 다운로드 (feat. 어노테이션만들기, (0) | 2024.12.10 |
| [SpringBoot] ResponseEntity로 Http 코드에 따라 응답데이터 반환하기 (1) | 2024.12.06 |
| [SpringBoot] getReader 오류 발생 (해결) (2) | 2024.12.02 |
| [Springboot] 400에러페이지 설정하기 (0) | 2023.07.05 |
- Total
- Today
- Yesterday
- 시청역숙소
- MySQL
- menu만들기
- 스프링부트
- 데이터베이스
- csv다운로드
- MAC
- httpcode
- 판교테크원타워맛집
- 유에이치스위트서울스퀘어
- xcrunerror
- 신사동이자카야
- 바디캐싱
- cachedbodyhttpservletrequest
- 논클러스터 인덱스
- 사용자별메뉴
- 오리지널팬케이스하우스
- 500에러관리
- 디비개발프로세스
- 400에러관리
- csv업로드
- springboot
- 시청역놀곳
- 컬럼타입변경
- 디너요리추천
- 권한별메뉴만들기
- 재귀구문
- 오리지널팬케이스하우스 판교점
- 유에이치스위트
- 데이터업로드
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |