728x90
1.@EnableMethodSecurity 설정 (SecurityConfig)
EnableMethodSecurity는 메소드 보안을 활성화하는 설정이다.
PreAuthorize을 사용하기 위해 prePostEnabled 옵션을 true 로 설정하였다.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
public class SecurityConfig {
}
2.createToken id,role 추가 (JwtTokenProvider)
createToken을 할때 claims를 사용하여 PostAuthorize 에 사용할 role과 id를 추가해준다.
// JWT 토큰 생성
public String createToken(String userId, String role,Long id) {
return Jwts.builder()
.claims().empty().add("role", role).add("id", id) // role,id 추가
.and()
.subject(userId)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(key, Jwts.SIG.HS256)
.compact();
}
3.JWT 추출 메소드(JwtTokenProvider)
JWT에서 넣은 role과 id를 추출할수있는 메소드들을 추가한다.
// JWT에서 역할 추출
public String getRoleFromToken(String token) {
return Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(token)
.getPayload()
.get("role", String.class);
}
//JWT에서 id 추출
public Long getIdFromToken(String token) {
return Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(token)
.getPayload()
.get("id", Long.class);
}
4.CustomUserDetails
Spring Security에서 제공하는 UserDetails 구현체를 만든다.
User 클래스를 확장하여 ID 필드를 추가한다.
public class CustomUserDetails extends User {
private final Long id;
public CustomUserDetails(Long id, String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
this.id = id;
}
public Long getId() {
return id;
}
}
5.doFilterInternal 수정 (JwtAuthenticationFilter)
만든 CustomUserDetails에 JWT에서 추출한 속성들을 넣어서객체를 만들고 .UsernamePasswordAuthenticationToken에 인증 정보를 저장한다.
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain chain) throws ServletException, IOException {
String token = getTokenFromRequest(request);
if (StringUtils.hasText(token) && jwtTokenProvider.validateToken(token)) {
String userId = jwtTokenProvider.getUserIdFromToken(token);
String role = jwtTokenProvider.getRoleFromToken(token);
Long id = jwtTokenProvider.getIdFromToken(token);
List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role));
UserDetails userDetails = new CustomUserDetails(id, userId, "", authorities);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
null, authorities);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
log.info("인증 완료: 사용자 ID = {}, 역할 = {}", userId, role);
}
chain.doFilter(request, response);
}
6.@PreAuthorize 사용
Spring Expression Language (SpEL) 표현식을 통해 권한이나 사용자 정보를 기반으로 접근 제어한다.
//맴버의 구매한 상품 리스트 조회
@GetMapping("/{memberId}/orders")
@PreAuthorize("hasRole('ROLE_ADMIN') or #memberId == authentication.principal.id")
public ResponseEntity<List<OrderItemResponseDto>> getOrders(@PathVariable Long memberId) {
List<OrderItem> orderItem = customerService.getOrders(memberId);
List<OrderItemResponseDto> responseDto = orderItem.stream()
.map(OrderItemResponseDto::fromEntity)
.collect(Collectors.toList());
return ResponseEntity.ok(responseDto);
}
728x90
'BackEnd > SpringBoot' 카테고리의 다른 글
[SpringBoot] 쇼핑몰 Entity 추가, 엔티티 어노테이션 상세 사용법 (0) | 2025.03.01 |
---|---|
[SpringBoot] 역할 접근권한설정, 상품 소유 인증 (0) | 2025.02.25 |
[SpringBoot] 쇼핑몰 상품 엔드포인트제작,예외처리, 로그설정 (0) | 2025.02.24 |