SecurityUtil ํด๋์ค ์์ฑ
package com.oliviarla.tutorial.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Optional;
public class SecurityUtil {
private static final Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
private SecurityUtil() {
}
public static Optional<String> getCurrentUsername() {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
logger.debug("Security Context์ ์ธ์ฆ ์ ๋ณด๊ฐ ์์ต๋๋ค.");
return Optional.empty();
}
String username = null;
if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
username = springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof String) {
username = (String) authentication.getPrincipal();
}
return Optional.ofNullable(username);
}
}
JwtFilter ํด๋์ค์ DoFilter ๋ฉ์๋์์ ์ ์ฅํ Security Context์ ์ธ์ฆ ์ ๋ณด์์ username์ ๋ฐํ
UserSerivice ํด๋์ค ์์ฑ
package com.oliviarla.tutorial.service;
import com.oliviarla.tutorial.dto.UserDto;
import com.oliviarla.tutorial.entity.Authority;
import com.oliviarla.tutorial.entity.User;
import com.oliviarla.tutorial.repository.UserRepository;
import com.oliviarla.tutorial.util.SecurityUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.Optional;
@Service
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
@Transactional
public User signup(UserDto userDto) {
if (userRepository.findOneWithAuthoritiesByUsername(userDto.getUsername()).orElse(null) != null) {
throw new RuntimeException("์ด๋ฏธ ๊ฐ์
๋์ด ์๋ ์ ์ ์
๋๋ค.");
}
Authority authority = Authority.builder()
.authorityName("ROLE_USER")
.build();
User user = User.builder()
.username(userDto.getUsername())
.password(passwordEncoder.encode(userDto.getPassword()))
.nickname(userDto.getNickname())
.authorities(Collections.singleton(authority))
.activated(true)
.build();
return userRepository.save(user);
}
@Transactional(readOnly = true)
public Optional<User> getUserWithAuthorities(String username) {
return userRepository.findOneWithAuthoritiesByUsername(username);
}
@Transactional(readOnly = true)
public Optional<User> getMyUserWithAuthorities() {
return SecurityUtil.getCurrentUsername().flatMap(userRepository::findOneWithAuthoritiesByUsername);
}
}
UserRepository, PasswordEncoder๋ฅผ ์ฃผ์ ๋ฐ์
signup(): ๊ฐ์ ๋์ด ์๋ ์ฌ์ฉ์์ธ์ง ํ์ธํ๊ณ UserDto ๊ฐ์ฒด์ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Authority, User ๊ฐ์ฒด ์์ฑํด DB์ ์ ์ฅ, ์ด ๋ฉ์๋๋ก ์์ฑ๋ ์ฌ์ฉ์๋ ROLE_USER ๊ถํ๋ง ์์ ๊ฐ๋ฅ
getUserWithAuthorities(): username์ผ๋ก ์ฌ์ฉ์์ ๊ถํ ์ ๋ณด๋ฅผ ๊ฒ์
getMyUserWithAuthorities(): ํ์ฌ ์ฌ์ฉ์์ username ๊ฐ์ ธ์ ์ฌ์ฉ์ ์ ๋ณด, ๊ถํ ์ ๋ณด ๋ฐํ
UserController ํด๋์ค ์์ฑ
package com.oliviarla.tutorial.controller;
import com.oliviarla.tutorial.dto.UserDto;
import com.oliviarla.tutorial.entity.User;
import com.oliviarla.tutorial.service.UserService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/signup")
public ResponseEntity<User> signup(
@Valid @RequestBody UserDto userDto
) {
return ResponseEntity.ok(userService.signup(userDto));
}
@GetMapping("/user")
@PreAuthorize("hasAnyRole('USER','ADMIN')")
public ResponseEntity<User> getMyUserInfo() {
return ResponseEntity.ok(userService.getMyUserWithAuthorities().get());
}
@GetMapping("/user/{username}")
@PreAuthorize("hasAnyRole('ADMIN')")
public ResponseEntity<User> getUserInfo(@PathVariable String username) {
return ResponseEntity.ok(userService.getUserWithAuthorities(username).get());
}
}
signup(): ํ์๊ฐ์ API, permitAll์ผ๋ก ๊ถํ ์์ด ํธ์ถ ๊ฐ๋ฅ
getMyUserInfo(): ํ์ฌ Security Context์ ์ ์ฅ๋์ด ์๋ ์ธ์ฆ ์ ๋ณด์ username์ ๊ธฐ์ค์ผ๋ก ํ ์ฌ์ฉ์ ์ ๋ณด ๋ฐ ๊ถํ ์ ๋ณด ๋ฐํ
getUserInfo(): username์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ ฅ๋ฐ์ ์ฌ์ฉ์์ ๊ถํ ์ ๋ณด ๋ฐํ, @PreAuthorize๋ฅผ ์ฌ์ฉํด ROLE_ADMIN ๊ถํ์ ์์ ํ ํ ํฐ๋ง ํธ์ถํ ์ ์๋๋ก ํจ
ํ์ ๊ฐ์ ํ ์คํธ

๊ถํ ๊ฒ์ฆ ํ ์คํธ

authenticate API๋ฅผ ํตํด oliviarla ์ ์ ์ ํ ํฐ ํ๋

Authenticate API ํธ์ถ ์ Tests ์ฝ๋๋ฅผ ์ฌ์ฉํด ๋ด์๋ ์ ์ญ๋ณ์ jwt_tutorial_token์ผ๋ก ์ ์ ์ ๋ณด ๋ฐ ๊ถํ ์ ๋ณด ๋ฐํ๋ฐ์

/api/user/{username}์ ROLE_ADMIN ๊ถํ ๊ฐ์ง ์ฌ์ฉ์๋ง ์ ๊ทผ ๊ฐ๋ฅํ๋ฏ๋ก 403 ์๋ฌ ๋ฐํ
์ถ์ฒ: https://silvernine.me/wp/?p=1178
๋๊ธ