SpringBootProject/SringBoot_JWT_RestApi
Chaptor.05 - 회원가입 API 생성 , 권한검증 테스트
ironmask431
2022. 4. 3. 19:29
<진행 할 것>
- 회원가입 api 생성
- 권한검증 확인
1. util 패키지 생성 > SecurityUtil.java 클래스 생성
package com.leesh.springbootjwttutorial.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Slf4j
@Component
public class SecurityUtil {
//현재 security context에 인증된 사용자 username 조회
public static Optional<String> getCurrentUsername(){
final Authentication authentication = SecurityContextHolder
.getContext().getAuthentication();
if(authentication == null){
log.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);
}
}
2. service 패키지 > UserService.java 생성
package com.leesh.springbootjwttutorial.service;
import com.leesh.springbootjwttutorial.dto.UserDto;
import com.leesh.springbootjwttutorial.entity.Authority;
import com.leesh.springbootjwttutorial.entity.User;
import com.leesh.springbootjwttutorial.repository.UserRepository;
import com.leesh.springbootjwttutorial.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
//회원가입
@Transactional
public User signup(UserDto userDto){
if(userRepository.findOneWithAuthoritiesByEmail(userDto.getEmail()).orElse(null) != null){
throw new RuntimeException(("이미 가입되어 있는 유저입니다."));
}
//권한entity, 유저entity 생성
Authority authority = Authority.builder()
.authorityName("ROLE_USER")
.build();
User user = User.builder()
.email(userDto.getEmail())
.password(passwordEncoder.encode(userDto.getPassword())) //패스워드 암호화
.authorities(Collections.singleton(authority))
.activated(true)
.build();
return userRepository.save(user);
}
//email로 회원정보 조회
@Transactional(readOnly = true)
public Optional<User> getUserWithAuthorities(String email){
return userRepository.findOneWithAuthoritiesByEmail(email);
}
//현재 인증된 사용자의 회원정보 조회
@Transactional(readOnly = true)
public Optional<User> getMyUserWithAuthorities(){
log.info(SecurityUtil.getCurrentUsername().toString());
return SecurityUtil.getCurrentUsername()
.flatMap(email -> userRepository.findOneWithAuthoritiesByEmail(email));
}
}
3. UserController.java 생성
package com.leesh.springbootjwttutorial.controller;
import com.leesh.springbootjwttutorial.entity.User;
import com.leesh.springbootjwttutorial.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 유저 API 컨트롤러
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/user")
public class UserController {
private final UserService userService;
//현재인증된 사용자의 정보 조회 (나의 정보조회)
//USER, ADMIN 권한 접근 가능
@GetMapping("/myInfo")
@PreAuthorize("hasAnyRole('USER','ADMIN')")
public ResponseEntity<User> getMyUserInfo(){
return ResponseEntity.ok(userService.getMyUserWithAuthorities().get());
}
//EMAIL로 회원정보 조회
//ADMIN 권한 접근 가능
@GetMapping("/email/{email}")
@PreAuthorize("hasAnyRole('ADMIN')")
public ResponseEntity<User> getUserInfo(@PathVariable String email){
return ResponseEntity.ok(userService.getUserWithAuthorities(email).get());
}
}
4. JoinController.java 생성
package com.leesh.springbootjwttutorial.controller;
import com.leesh.springbootjwttutorial.dto.UserDto;
import com.leesh.springbootjwttutorial.entity.User;
import com.leesh.springbootjwttutorial.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* 회원가입 API 컨트롤러
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/join")
public class JoinController {
private final UserService userService;
//회원가입 - email, password 입력
@PostMapping("/signup")
public ResponseEntity<User> signup(@Valid @RequestBody UserDto userDto){
return ResponseEntity.ok(userService.signup(userDto));
}
}
5. 서버구동, /signup 회원가입 테스트, /login 로그인 테스트
회원가입 정상 확인
가입한 회원 id/pw로 로그인(토큰발급)도 정상 확인
h2 console 에서도 user 테이블에 정상 입력 된 것 확인함.
6. 권한 테스트 - User 권한을 가진 leesh@gmail.com 계정 토큰 으로 /myInfo 조회
> 정상 확인
7. User 권한을 가진 leesh@gmail.com 계정 토큰 으로 /api/user/email/{email} 조회
> 403 접근 거부 에러 확인
8. ADMIN 권한을 가진 admin@gmail.com 계정 토큰으로 /api/user/email/{email} 조회
먼저 admin@gmail.com 계정으로 로그인하여 토큰을 다시 발급 받은 후 api 실행
> 정상 확인