Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Spring Data JPA] 윤성원 미션 제출합니다. #52

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
//implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

implementation 'dev.akkinoc.spring.boot:logback-access-spring-boot-starter:4.0.0'

Expand Down
1 change: 1 addition & 0 deletions src/main/java/roomescape/RoomescapeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;

@SpringBootApplication
public class RoomescapeApplication {
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/roomescape/api/JwtDecoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package roomescape.api;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

public class JwtDecoder {
public static Long decodeJwtToken(String token) {
Long memberId = Long.valueOf(Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor("Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=".getBytes()))
.build()
.parseClaimsJws(token)
.getBody().getSubject());
return memberId;
}
}
25 changes: 25 additions & 0 deletions src/main/java/roomescape/api/JwtProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package roomescape.api;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import roomescape.member.Member;
import roomescape.member.MemberService;

@Component
public class JwtProvider {

@Value("${roomescape.auth.jwt.secret}")
private String secretKey;

public String createToken(Member member){
return Jwts.builder()
.setSubject(member.getId().toString())
.claim("name", member.getName())
.claim("role", member.getRole())
.signWith(Keys.hmacShaKeyFor(secretKey.getBytes()))
.compact();
}
}
46 changes: 46 additions & 0 deletions src/main/java/roomescape/auth/AdminInterceptor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package roomescape.auth;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import roomescape.api.JwtDecoder;
import roomescape.exception.NotFoundException;
import roomescape.exception.UnauthorizedException;
import roomescape.member.Member;
import roomescape.member.MemberService;
import roomescape.util.CookieUtil;

@Component
public class AdminInterceptor implements HandlerInterceptor {
private MemberService memberService;

public AdminInterceptor(MemberService memberService) {
this.memberService = memberService;
}

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
String token = CookieUtil.extractTokenFromCookie(request.getCookies());
Long id = JwtDecoder.decodeJwtToken(token);
Member member = memberService.findById(id);

if (member == null) {
throw new NotFoundException("유저를 찾을 수 없습니다.");
} else if (!member.getRole().equals("ADMIN")) {
throw new UnauthorizedException("관리자 회원이 아닙니다.");
}

return true;
} catch (NotFoundException | UnauthorizedException e) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write(e.getMessage());
return false;
} catch(Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("예상치 못한 오류가 발생했습니다.");
return false;
}
}
}
22 changes: 22 additions & 0 deletions src/main/java/roomescape/auth/AuthService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package roomescape.auth;

import org.springframework.stereotype.Service;
import roomescape.api.JwtDecoder;
import roomescape.member.dto.LoginMember;
import roomescape.member.Member;
import roomescape.member.MemberService;

@Service
public class AuthService {
private MemberService memberService;

public AuthService(MemberService memberService) {
this.memberService = memberService;
}

public LoginMember getLoginMemberWithToken(String token) {
Long id = JwtDecoder.decodeJwtToken(token);
Member member = memberService.findById(id);
return new LoginMember(member.getId(), member.getName(), member.getEmail(), member.getPassword());
}
}
22 changes: 22 additions & 0 deletions src/main/java/roomescape/config/InterceptorConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package roomescape.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import roomescape.auth.AdminInterceptor;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
private AdminInterceptor adminInterceptor;


public InterceptorConfig(AdminInterceptor adminInterceptor) {
this.adminInterceptor = adminInterceptor;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminInterceptor)
.addPathPatterns("/admin");
}
}
39 changes: 39 additions & 0 deletions src/main/java/roomescape/config/LoginMemberArgumentResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package roomescape.config;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import roomescape.api.JwtDecoder;
import roomescape.auth.AuthService;
import roomescape.member.Member;
import roomescape.util.CookieUtil;

@Component
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
private AuthService authService;

public LoginMemberArgumentResolver(AuthService authService) {
this.authService = authService;
}

@Override
public boolean supportsParameter(MethodParameter parameter) {
return Member.class.isAssignableFrom(parameter.getParameterType());
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
Cookie[] cookies = request.getCookies();
String token = CookieUtil.extractTokenFromCookie(cookies);
if(token == null){
return null;
}
return authService.getLoginMemberWithToken(token);
}
}
21 changes: 21 additions & 0 deletions src/main/java/roomescape/config/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package roomescape.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {
private final LoginMemberArgumentResolver loginMemberArgumentResolver;

public WebConfig(LoginMemberArgumentResolver loginMemberArgumentResolver) {
this.loginMemberArgumentResolver = loginMemberArgumentResolver;
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginMemberArgumentResolver);
}
}
7 changes: 7 additions & 0 deletions src/main/java/roomescape/exception/NotFoundException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package roomescape.exception;

public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
7 changes: 7 additions & 0 deletions src/main/java/roomescape/exception/UnauthorizedException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package roomescape.exception;

public class UnauthorizedException extends RuntimeException {
public UnauthorizedException(String message) {
super(message);
}
}
20 changes: 20 additions & 0 deletions src/main/java/roomescape/member/Member.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package roomescape.member;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
Expand All @@ -21,6 +29,18 @@ public Member(String name, String email, String password, String role) {
this.role = role;
}

public Member(Long id, String name, String email, String password, String role) {
this.id = id;
this.name = name;
this.email = email;
this.password = password;
this.role = role;
}

public Member() {

}

public Long getId() {
return id;
}
Expand Down
25 changes: 23 additions & 2 deletions src/main/java/roomescape/member/MemberController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import roomescape.member.dto.MemberRequest;
import roomescape.member.dto.MemberResponse;
import roomescape.util.CookieUtil;

import java.net.URI;

Expand All @@ -20,11 +23,29 @@ public MemberController(MemberService memberService) {
}

@PostMapping("/members")
public ResponseEntity createMember(@RequestBody MemberRequest memberRequest) {
MemberResponse member = memberService.createMember(memberRequest);
public ResponseEntity createMember(@RequestBody MemberRequest.Create memberRequest) {
MemberResponse.Create member = memberService.createMember(memberRequest);
return ResponseEntity.created(URI.create("/members/" + member.getId())).body(member);
}

@PostMapping("/login")
public ResponseEntity login(@RequestBody MemberRequest.Login request, HttpServletResponse response) {
String token = memberService.loginMember(request);
Cookie cookie = new Cookie("token", token);
cookie.setHttpOnly(true);
cookie.setPath("/");
response.addCookie(cookie);
return ResponseEntity.ok().build();
}

@GetMapping("/login/check")
public ResponseEntity checkLogin(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
String token = CookieUtil.extractTokenFromCookie(cookies);
MemberResponse.Check response = memberService.checkMember(token);
return ResponseEntity.ok(response);
}

@PostMapping("/logout")
public ResponseEntity logout(HttpServletResponse response) {
Cookie cookie = new Cookie("token", "");
Expand Down
55 changes: 0 additions & 55 deletions src/main/java/roomescape/member/MemberDao.java

This file was deleted.

10 changes: 10 additions & 0 deletions src/main/java/roomescape/member/MemberRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package roomescape.member;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {

Member findByEmailAndPassword(String email, String password);
}
19 changes: 0 additions & 19 deletions src/main/java/roomescape/member/MemberRequest.java

This file was deleted.

Loading