diff --git a/src/main/java/com/hanaro/starbucks/config/JwtUtil.java b/src/main/java/com/hanaro/starbucks/config/JwtUtil.java index 71defae..9c7a63d 100644 --- a/src/main/java/com/hanaro/starbucks/config/JwtUtil.java +++ b/src/main/java/com/hanaro/starbucks/config/JwtUtil.java @@ -31,7 +31,7 @@ public class JwtUtil { @PostConstruct protected void init() { - secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); + secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); // secret key 암호화 } public String createToken(String userId, List roleList) { @@ -51,11 +51,12 @@ public Authentication getAuthentication(String token) { UserDetails userDetails = userDetailsService.loadUserByUsername(userId); return new UsernamePasswordAuthenticationToken( userDetails, "", userDetails.getAuthorities() - ); + ); // 사용자 정보를 기반으로 토큰 생성 } + // http 요청에서 "TOKEN" 헤더 값을 읽어오는 메소드 public String resolveToken(HttpServletRequest request) { - return request.getHeader("X-AUTH-TOKEN"); + return request.getHeader("TOKEN"); } public boolean validateToken(String token){ diff --git a/src/main/java/com/hanaro/starbucks/config/SecurityConfig.java b/src/main/java/com/hanaro/starbucks/config/SecurityConfig.java index 2ffc000..f0f5ed6 100644 --- a/src/main/java/com/hanaro/starbucks/config/SecurityConfig.java +++ b/src/main/java/com/hanaro/starbucks/config/SecurityConfig.java @@ -1,5 +1,6 @@ package com.hanaro.starbucks.config; +import com.hanaro.starbucks.service.impl.UserDetailsServiceImpl; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -27,37 +28,29 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .csrf((auth) -> auth.disable()) .cors((cors) -> cors.configurationSource(corsConfigurationSource())) -// .authorizeHttpRequests((auth) -> auth -// // 로그인과 회원가입은 모든 사용자에게 허용한다. -// .requestMatchers( -// new AntPathRequestMatcher("/login"), -// new AntPathRequestMatcher("/signup") -// ).permitAll() // 권한이 있든 말든 모두 접근 가능 -// // admin일 경우에만 /admin에 대한 요청에서 접근을 허용한다. -// .requestMatchers("/admin").hasRole("ADMIN") -// // 그 외 모든 요청은 인증된 사용자에게만 허용한다. -// .anyRequest().authenticated() -// ) -// .formLogin((formLogin) -> formLogin -// .loginProcessingUrl("/login") -// .successHandler(((request, response, authentication) -> { -// System.out.println("로그인 성공했습니다."); -// response.sendRedirect("/"); -// })) -// .permitAll() -// ); + .authorizeHttpRequests((auth) -> auth + // 로그인과 회원가입은 모든 사용자에게 허용한다. + .requestMatchers( + new AntPathRequestMatcher("/api/v1/users/login"), + new AntPathRequestMatcher("/api/v1/users/signup") + ).permitAll() // 권한이 있든 말든 모두 접근 가능 + // admin일 경우에만 /admin에 대한 요청에서 접근을 허용한다. + .requestMatchers("/api/v1/users/admin/**").hasRole("ADMIN") + .requestMatchers("/api/v1/products/admin/**").hasRole("ADMIN") + .requestMatchers("/api/v1/orders/admin/**").hasRole("ADMIN") + // 그 외 모든 요청은 인증된 사용자에게만 허용한다. + .anyRequest().permitAll() + ) - .authorizeHttpRequests( (auth) -> auth - .requestMatchers( new AntPathRequestMatcher("/**") ) - .permitAll()) +// .authorizeHttpRequests( (auth) -> auth +// .requestMatchers( new AntPathRequestMatcher("/**") ) +// .permitAll()) .sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy( SessionCreationPolicy.STATELESS // 세션에 저장하지 않겠다. 기본이 세션에 저장하는 것 )) - .addFilterBefore(new JwtAuthenticationFilter(jwtConfig), - UsernamePasswordAuthenticationFilter.class); - + .addFilterBefore(new JwtAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class); return http.build(); } diff --git a/src/main/java/com/hanaro/starbucks/controller/MemberController.java b/src/main/java/com/hanaro/starbucks/controller/MemberController.java index b739b0e..726a6bd 100644 --- a/src/main/java/com/hanaro/starbucks/controller/MemberController.java +++ b/src/main/java/com/hanaro/starbucks/controller/MemberController.java @@ -9,20 +9,24 @@ import org.springframework.web.bind.annotation.*; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import static com.hanaro.starbucks.util.APIConstant.API_VERSION; @RestController @RequiredArgsConstructor -@RequestMapping("/api/v1/users") +@RequestMapping(API_VERSION + "/users") public class MemberController { private final MemberService memberService; private final JwtUtil jwtUtil; - @GetMapping("") + @GetMapping("/admin") public List getUsers(){ return memberService.getUsers(); } - @GetMapping("/{userIdx}") + @GetMapping("/admin/{userIdx}") public MemberResDto getUser(@PathVariable int userIdx){ return memberService.getUser(userIdx); } @@ -30,9 +34,7 @@ public MemberResDto getUser(@PathVariable int userIdx){ @PostMapping("/signup") @ResponseBody public ResponseEntity signup(@RequestBody SignupReqDto user) { - System.out.println(user); boolean findUser = memberService.findUserByUserId(user.getUserId()); - System.out.println(findUser); if (!findUser) { MemberResDto newUser = memberService.createUser(user); return ResponseEntity.ok(newUser.getUserId()); @@ -44,9 +46,13 @@ public ResponseEntity signup(@RequestBody SignupReqDto user) { @ResponseBody public ResponseEntity login(@RequestBody LoginReqDto user) { MemberResDto findUser = memberService.findUserByUserIdAndUserPw(user.getUserId(), user.getUserPw()); + System.out.println(findUser); if (findUser != null) { String token = jwtUtil.createToken(findUser.getUserId(), Arrays.asList(findUser.getUserRole())); - return ResponseEntity.ok(token); + Map response = new HashMap<>(); + response.put("user", findUser); // 사용자 정보 + response.put("token", token); // 토큰 + return ResponseEntity.ok(response); } else { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("로그인에 실패하였습니다. 아이디와 비밀번호를 확인해주세요."); } diff --git a/src/main/java/com/hanaro/starbucks/controller/OrderController.java b/src/main/java/com/hanaro/starbucks/controller/OrderController.java index a4ebc5c..3303207 100644 --- a/src/main/java/com/hanaro/starbucks/controller/OrderController.java +++ b/src/main/java/com/hanaro/starbucks/controller/OrderController.java @@ -3,6 +3,7 @@ import com.hanaro.starbucks.dto.orders.OrderEditReqDto; import com.hanaro.starbucks.dto.orders.OrderResDto; import com.hanaro.starbucks.service.OrderService; +import io.jsonwebtoken.Jwts; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -21,6 +22,7 @@ public class OrderController { public List getOrders() { return orderService.getOrders(); } + @GetMapping("/{orderIdx}") public OrderResDto getOrder(@PathVariable int orderIdx) { return orderService.getOrder(orderIdx); diff --git a/src/main/java/com/hanaro/starbucks/dto/member/MemberResDto.java b/src/main/java/com/hanaro/starbucks/dto/member/MemberResDto.java index 32fc0ad..000a0ea 100644 --- a/src/main/java/com/hanaro/starbucks/dto/member/MemberResDto.java +++ b/src/main/java/com/hanaro/starbucks/dto/member/MemberResDto.java @@ -1,6 +1,7 @@ package com.hanaro.starbucks.dto.member; import com.hanaro.starbucks.entity.Member; +import com.hanaro.starbucks.enumeration.UserRole; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -30,7 +31,7 @@ public MemberResDto(Member user){ this.userId = user.getUserId(); this.userPw = user.getUserPw(); this.userNickname = user.getUserNickname(); - this.userRole = user.getUserRole(); + this.userRole = String.valueOf(user.getUserRole()); this.userPoint = user.getUserPoint(); this.userJoinDate = user.getUserJoinDate(); } diff --git a/src/main/java/com/hanaro/starbucks/dto/member/MemberUpdateReqDto.java b/src/main/java/com/hanaro/starbucks/dto/member/MemberUpdateReqDto.java index ffd353f..4ed77b6 100644 --- a/src/main/java/com/hanaro/starbucks/dto/member/MemberUpdateReqDto.java +++ b/src/main/java/com/hanaro/starbucks/dto/member/MemberUpdateReqDto.java @@ -1,5 +1,6 @@ package com.hanaro.starbucks.dto.member; +import com.hanaro.starbucks.enumeration.UserRole; import lombok.Getter; import java.time.LocalDate; @@ -9,7 +10,7 @@ public class MemberUpdateReqDto { private String userId; private String userPw; private String userNickname; - private String userRole; + private UserRole userRole; private Integer userPoint; private LocalDate userJoinDate; } \ No newline at end of file diff --git a/src/main/java/com/hanaro/starbucks/entity/Member.java b/src/main/java/com/hanaro/starbucks/entity/Member.java index 23397d2..d1f2104 100644 --- a/src/main/java/com/hanaro/starbucks/entity/Member.java +++ b/src/main/java/com/hanaro/starbucks/entity/Member.java @@ -1,18 +1,26 @@ package com.hanaro.starbucks.entity; import com.hanaro.starbucks.dto.member.MemberUpdateReqDto; +import com.hanaro.starbucks.enumeration.UserRole; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDate; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; @Entity @Getter @NoArgsConstructor @Table(name = "user") -public class Member { +public class Member implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -29,7 +37,8 @@ public class Member { private String userNickname; @Column(name = "user_role") - private String userRole; + @Enumerated(EnumType.STRING) + private UserRole userRole; @Column(name = "user_point") private int userPoint; @@ -42,7 +51,7 @@ public Member(String userId, String userPw, String userNickname) { this.userId = userId; this.userPw = userPw; this.userNickname = userNickname; - this.userRole = "USER"; + this.userRole = UserRole.USER; this.userPoint = 0; } @@ -54,4 +63,39 @@ public void update(MemberUpdateReqDto dto) { this.userPoint = dto.getUserPoint(); this.userJoinDate = LocalDate.now(); } + + @Override + public Collection getAuthorities() { + //계정의 권한 목록을 리턴함. + Set roles = new HashSet<>(); + roles.add(new SimpleGrantedAuthority(userRole.getValue())); + return roles; + } + + @Override + public String getUsername() { + return this.userId; //계정의 고유한 아이디 리턴 + } + + @Override + public String getPassword() { + return this.userPw; //계정의 암호 리턴 + } + + @Override + public boolean isAccountNonExpired() { + return true; //계정의 만료 여부 리턴 - true는 사용가능하다는 의미 + } + @Override + public boolean isAccountNonLocked() { + return true; //계정의 잠김 여부 리턴 + } + @Override + public boolean isCredentialsNonExpired() { + return true; //비밀번호 만료 여부 리턴 + } + @Override + public boolean isEnabled() { + return true; //계정의 활성화 여부 리턴 + } } \ No newline at end of file diff --git a/src/main/java/com/hanaro/starbucks/enumeration/UserRole.java b/src/main/java/com/hanaro/starbucks/enumeration/UserRole.java new file mode 100644 index 0000000..817c048 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/enumeration/UserRole.java @@ -0,0 +1,13 @@ +package com.hanaro.starbucks.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum UserRole { + USER("ROLE_USER"), + ADMIN("ROLE_ADMIN"); + + private String value; +} diff --git a/src/main/java/com/hanaro/starbucks/service/impl/UserDetailsServiceImpl.java b/src/main/java/com/hanaro/starbucks/service/impl/UserDetailsServiceImpl.java new file mode 100644 index 0000000..353f3ad --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/service/impl/UserDetailsServiceImpl.java @@ -0,0 +1,23 @@ +package com.hanaro.starbucks.service.impl; + +import com.hanaro.starbucks.entity.Member; +import com.hanaro.starbucks.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@RequiredArgsConstructor +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + private final MemberRepository memberRepository; + + @Override + public Member loadUserByUsername(String userId) throws UsernameNotFoundException { + Optional optional = Optional.ofNullable(memberRepository.findByUserId(userId).orElseThrow(() -> new BadCredentialsException("아이디에 맞는 회원 정보를 찾을 수 없습니다."))); + return optional.get(); + } +} \ No newline at end of file