diff --git a/src/main/java/com/pjw/retry_view/config/WebConfig.java b/src/main/java/com/pjw/retry_view/config/WebConfig.java index 3cecda8..adb243c 100644 --- a/src/main/java/com/pjw/retry_view/config/WebConfig.java +++ b/src/main/java/com/pjw/retry_view/config/WebConfig.java @@ -2,6 +2,7 @@ import com.pjw.retry_view.converter.UserStateEnumConverter; import com.pjw.retry_view.filter.JWTVerifyFilter; +import com.pjw.retry_view.filter.UserAuthorizationFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,9 +14,11 @@ @Configuration public class WebConfig implements WebMvcConfigurer { private final JWTVerifyFilter jwtverifyFilter; + private final UserAuthorizationFilter userAuthorizationFilter; - public WebConfig(JWTVerifyFilter jwtVerifyFilter){ + public WebConfig(JWTVerifyFilter jwtVerifyFilter, UserAuthorizationFilter userAuthorizationFilter){ this.jwtverifyFilter = jwtVerifyFilter; + this.userAuthorizationFilter = userAuthorizationFilter; } @Bean @@ -27,6 +30,16 @@ public FilterRegistrationBean jwtVerifyFilterBean(){ return jwtVerifyFilterBean; } + @Bean + public FilterRegistrationBean userAuthorizationFilterBean(){ + FilterRegistrationBean userAuthorizationFilterBean = new FilterRegistrationBean<>(); + userAuthorizationFilterBean.setFilter(userAuthorizationFilter); + userAuthorizationFilterBean.setOrder(2); + userAuthorizationFilterBean.setUrlPatterns(List.of("*")); + + return userAuthorizationFilterBean; + } + @Override public void addFormatters(FormatterRegistry registry) { WebMvcConfigurer.super.addFormatters(registry); diff --git a/src/main/java/com/pjw/retry_view/controller/AdminController.java b/src/main/java/com/pjw/retry_view/controller/AdminController.java new file mode 100644 index 0000000..930a29d --- /dev/null +++ b/src/main/java/com/pjw/retry_view/controller/AdminController.java @@ -0,0 +1,44 @@ +package com.pjw.retry_view.controller; + +import com.pjw.retry_view.dto.UserAuth; +import com.pjw.retry_view.dto.UserDTO; +import com.pjw.retry_view.request.RegistUserRequest; +import com.pjw.retry_view.response.RegistUserResponse; +import com.pjw.retry_view.service.UserService; +import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/admin") +public class AdminController { + private final UserService userService; + + public AdminController(UserService userService){ + this.userService = userService; + } + + @PostMapping("/regist") + public ResponseEntity registAdminUser(@RequestBody @Valid RegistUserRequest userReq, BindingResult bindingResult) { + RegistUserResponse response = new RegistUserResponse(); + HttpStatus httpStatus = HttpStatus.OK; + + if (bindingResult.hasErrors()) { + response.setBindingErrors(bindingResult.getAllErrors()); + httpStatus = HttpStatus.BAD_REQUEST; + } else { + UserDTO user = userReq.toUserDTO(); + user.setRole(UserAuth.ADMIN); + UserDTO registUser = userService.saveUser(user); + response.setName(registUser.getName()); + response.setLoginId(registUser.getLoginId()); + response.setNickname(registUser.getNickname()); + } + + return new ResponseEntity(response, httpStatus); + } +} diff --git a/src/main/java/com/pjw/retry_view/controller/LoginController.java b/src/main/java/com/pjw/retry_view/controller/LoginController.java index 121df23..275a52a 100644 --- a/src/main/java/com/pjw/retry_view/controller/LoginController.java +++ b/src/main/java/com/pjw/retry_view/controller/LoginController.java @@ -31,7 +31,7 @@ public LoginController(UserService userService, JWTService jwtService){ public ResponseEntity userLogin(@RequestBody @Valid LoginRequest loginReq){ UserDTO user = userService.userLogin(loginReq); - UserInfo userInfo = new UserInfo(user.getName(), user.getLoginId()); + UserInfo userInfo = new UserInfo(user.getName(), user.getLoginId(), user.getRole()); LoginResponse response = new LoginResponse(); String refreshToken = JWTUtil.createRefreshToken(); diff --git a/src/main/java/com/pjw/retry_view/controller/UserController.java b/src/main/java/com/pjw/retry_view/controller/UserController.java index 8c792e7..9c6bf72 100644 --- a/src/main/java/com/pjw/retry_view/controller/UserController.java +++ b/src/main/java/com/pjw/retry_view/controller/UserController.java @@ -1,5 +1,6 @@ package com.pjw.retry_view.controller; +import com.pjw.retry_view.dto.UserAuth; import com.pjw.retry_view.dto.UserDTO; import com.pjw.retry_view.request.RegistUserRequest; import com.pjw.retry_view.response.RegistUserResponse; @@ -44,7 +45,9 @@ public ResponseEntity registUser(@RequestBody @Valid RegistU response.setBindingErrors(bindingResult.getAllErrors()); httpStatus = HttpStatus.BAD_REQUEST; } else { - UserDTO registUser = userService.saveUser(userReq.toUserDTO()); + UserDTO user = userReq.toUserDTO(); + user.setRole(UserAuth.USER); + UserDTO registUser = userService.saveUser(user); response.setName(registUser.getName()); response.setLoginId(registUser.getLoginId()); response.setNickname(registUser.getNickname()); diff --git a/src/main/java/com/pjw/retry_view/converter/UserAutnEnumConverter.java b/src/main/java/com/pjw/retry_view/converter/UserAutnEnumConverter.java new file mode 100644 index 0000000..eaa610e --- /dev/null +++ b/src/main/java/com/pjw/retry_view/converter/UserAutnEnumConverter.java @@ -0,0 +1,19 @@ +package com.pjw.retry_view.converter; + +import com.pjw.retry_view.dto.UserAuth; +import io.micrometer.common.util.StringUtils; +import jakarta.persistence.AttributeConverter; + +public class UserAutnEnumConverter implements AttributeConverter { + @Override + public String convertToDatabaseColumn(UserAuth userAuth) { + if(userAuth == null) return UserAuth.USER.getCode(); + return userAuth.getCode(); + } + + @Override + public UserAuth convertToEntityAttribute(String code) { + if(StringUtils.isBlank(code)) return UserAuth.USER; + return UserAuth.getValue(code); + } +} diff --git a/src/main/java/com/pjw/retry_view/converter/UserStateEnumConverter.java b/src/main/java/com/pjw/retry_view/converter/UserStateEnumConverter.java index 78e2989..60d0ea0 100644 --- a/src/main/java/com/pjw/retry_view/converter/UserStateEnumConverter.java +++ b/src/main/java/com/pjw/retry_view/converter/UserStateEnumConverter.java @@ -8,14 +8,12 @@ public class UserStateEnumConverter implements AttributeConverterauth.getCode().equals(code)).findFirst().orElse(UserAuth.USER); + } +} diff --git a/src/main/java/com/pjw/retry_view/dto/UserDTO.java b/src/main/java/com/pjw/retry_view/dto/UserDTO.java index d62caa5..a8daf10 100644 --- a/src/main/java/com/pjw/retry_view/dto/UserDTO.java +++ b/src/main/java/com/pjw/retry_view/dto/UserDTO.java @@ -17,7 +17,7 @@ public class UserDTO implements Serializable { private Gender gender; private String phone; private String address; - private String role; + private UserAuth role; private String loginId; private String password; private String nickname; diff --git a/src/main/java/com/pjw/retry_view/dto/UserInfo.java b/src/main/java/com/pjw/retry_view/dto/UserInfo.java index 628ca51..965918b 100644 --- a/src/main/java/com/pjw/retry_view/dto/UserInfo.java +++ b/src/main/java/com/pjw/retry_view/dto/UserInfo.java @@ -8,10 +8,12 @@ public class UserInfo { private String name; private String loginId; + private UserAuth role; public UserInfo(){} - public UserInfo(String name, String loginId){ + public UserInfo(String name, String loginId, UserAuth auth){ this.name = name; this.loginId = loginId; + this.role = auth; } } diff --git a/src/main/java/com/pjw/retry_view/dto/UserState.java b/src/main/java/com/pjw/retry_view/dto/UserState.java index 95d2b38..f63d871 100644 --- a/src/main/java/com/pjw/retry_view/dto/UserState.java +++ b/src/main/java/com/pjw/retry_view/dto/UserState.java @@ -1,5 +1,7 @@ package com.pjw.retry_view.dto; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.Getter; import java.util.Arrays; @@ -8,11 +10,13 @@ public enum UserState{ NORMAL(1), WITHDRAW(9); + @JsonValue private final int code; UserState(int code){ this.code = code; } + @JsonCreator public static UserState getValue(int code) { return Arrays.stream(UserState.values()).filter(state -> state.getCode() == code).findFirst().orElse(UserState.NORMAL); } diff --git a/src/main/java/com/pjw/retry_view/entity/User.java b/src/main/java/com/pjw/retry_view/entity/User.java index 5041cd0..e5f89b9 100644 --- a/src/main/java/com/pjw/retry_view/entity/User.java +++ b/src/main/java/com/pjw/retry_view/entity/User.java @@ -1,7 +1,9 @@ package com.pjw.retry_view.entity; +import com.pjw.retry_view.converter.UserAutnEnumConverter; import com.pjw.retry_view.converter.UserStateEnumConverter; import com.pjw.retry_view.dto.Gender; +import com.pjw.retry_view.dto.UserAuth; import com.pjw.retry_view.dto.UserDTO; import com.pjw.retry_view.dto.UserState; import jakarta.persistence.*; @@ -29,7 +31,8 @@ public class User { @Column(name = "address") private String address; @Column(name = "role") - private String role; + @Convert(converter = UserAutnEnumConverter.class) + private UserAuth role; @Column(name = "login_id") private String loginId; @Column(name = "password") diff --git a/src/main/java/com/pjw/retry_view/filter/UserAuthorizationFilter.java b/src/main/java/com/pjw/retry_view/filter/UserAuthorizationFilter.java new file mode 100644 index 0000000..9817aa9 --- /dev/null +++ b/src/main/java/com/pjw/retry_view/filter/UserAuthorizationFilter.java @@ -0,0 +1,38 @@ +package com.pjw.retry_view.filter; + +import com.pjw.retry_view.dto.UserAuth; +import com.pjw.retry_view.util.JWTUtil; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +@Component +public class UserAuthorizationFilter extends OncePerRequestFilter { + private static final Set excludeUrlPatterns = new HashSet<>(Set.of("/login","/users/regist","/admin/regist")); + private static final String ADMIN_URL = "/admin"; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String uri = request.getRequestURI(); + String jwt = request.getHeader("Authorization"); + UserAuth userAuth = JWTUtil.getUserAuthInJWT(jwt); + if(uri.startsWith(ADMIN_URL) && !UserAuth.ADMIN.equals(userAuth)){ + response.sendError(HttpStatus.UNAUTHORIZED.value(), "권한이 없습니다."); + } + filterChain.doFilter(request,response); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + String uri = request.getRequestURI(); + return excludeUrlPatterns.contains(uri); + } +} diff --git a/src/main/java/com/pjw/retry_view/request/RegistUserRequest.java b/src/main/java/com/pjw/retry_view/request/RegistUserRequest.java index 251ea16..0890ea5 100644 --- a/src/main/java/com/pjw/retry_view/request/RegistUserRequest.java +++ b/src/main/java/com/pjw/retry_view/request/RegistUserRequest.java @@ -1,10 +1,9 @@ package com.pjw.retry_view.request; -import com.pjw.retry_view.converter.UserStateEnumConverter; import com.pjw.retry_view.dto.Gender; +import com.pjw.retry_view.dto.UserAuth; import com.pjw.retry_view.dto.UserDTO; import com.pjw.retry_view.dto.UserState; -import jakarta.persistence.Convert; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Getter; diff --git a/src/main/java/com/pjw/retry_view/service/JWTService.java b/src/main/java/com/pjw/retry_view/service/JWTService.java index 6b1b225..88c706a 100644 --- a/src/main/java/com/pjw/retry_view/service/JWTService.java +++ b/src/main/java/com/pjw/retry_view/service/JWTService.java @@ -28,7 +28,7 @@ public JWToken renewAccessToken(String refreshToken) throws InvalidTokenExceptio } UserDTO user = userRepository.findByRefreshToken(refreshToken).map(User::toDTO).orElseThrow(UserNotFoundException::new); - UserInfo userInfo = new UserInfo(user.getName(), user.getLoginId()); + UserInfo userInfo = new UserInfo(user.getName(), user.getLoginId(), user.getRole()); boolean isExpired = JWTUtil.isTokenExpired(refreshToken); if (isExpired) { diff --git a/src/main/java/com/pjw/retry_view/util/JWTUtil.java b/src/main/java/com/pjw/retry_view/util/JWTUtil.java index a04a7c4..3d7b17e 100644 --- a/src/main/java/com/pjw/retry_view/util/JWTUtil.java +++ b/src/main/java/com/pjw/retry_view/util/JWTUtil.java @@ -1,5 +1,6 @@ package com.pjw.retry_view.util; +import com.pjw.retry_view.dto.UserAuth; import com.pjw.retry_view.dto.UserInfo; import com.pjw.retry_view.exception.InvalidTokenException; import com.pjw.retry_view.repository.UserRepository; @@ -22,6 +23,7 @@ public class JWTUtil { private static final long REFRESH_TOKEN_EXPIRED = 1000 * 60 * 60 * 24 * 7; private static final String USER_INFO_NAME = "name"; private static final String USER_INFO_LOGIN_ID = "loginId"; + private static final String USER_INFO_ROLE = "role"; //private static final String AUTH_KEY = "Authorization"; private static final String BEARER_TYPE = "Bearer";// 7day @@ -38,6 +40,7 @@ public static String createAccessToken(UserInfo userInfo){ Map claims = new HashMap<>(); claims.put(USER_INFO_NAME, userInfo.getName()); claims.put(USER_INFO_LOGIN_ID, userInfo.getLoginId()); + claims.put(USER_INFO_ROLE, userInfo.getRole().getCode()); return Jwts.builder() .claims(claims) .issuer("issuer") @@ -66,6 +69,12 @@ public static Claims getClaims(String token)throws InvalidTokenException { .getPayload(); } + public static UserAuth getUserAuthInJWT(String token){ + Claims claims = getClaims(token); + String authCode = claims.get(USER_INFO_ROLE,String.class); + return UserAuth.getValue(authCode); + } + public static boolean isValidateToken(String token){ if(StringUtils.isBlank(token)) return false; token = splitToken(token);