Skip to content
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: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

124 changes: 124 additions & 0 deletions .idea/uiDesigner.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions android-lesson-07
Submodule android-lesson-07 added at fddad1
12 changes: 12 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ dependencies {
implementation('org.springframework.boot:spring-boot-starter-thymeleaf')



// ==================================================
// AWS SDK
// ==================================================

// AWS SDK를 사용하기 전, 전체적인 버전 관리를 위해 BOM(Build Of Material)을 추가합니다.
// 해당 프로젝트는 AWS SDK 1.12.529 버전의 BOM을 사용하기에, 다른 AWS 의존성 또한 해당 버전으로 고정됩니다.
implementation platform('com.amazonaws:aws-java-sdk-bom:1.12.529')
// AWS S3을 사용하기 위해 S3 의존성을 추가합니다.
implementation('com.amazonaws:aws-java-sdk-s3')


// ==================================================
// JWT
// ==================================================
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/kr/easw/lesson07/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kr.easw.lesson07;

public class Constants {
public static final String AUTHORITY_GUEST = "GUEST";
public static final String AUTHORITY_ADMIN = "ADMIN";

}
1 change: 1 addition & 0 deletions src/main/java/kr/easw/lesson07/Lesson07Example.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.easw.lesson07;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/kr/easw/lesson07/auth/JpaUserDetailsService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package kr.easw.lesson07.auth;

import kr.easw.lesson07.Constants;
import kr.easw.lesson07.model.dto.UserDataEntity;
import kr.easw.lesson07.model.repository.UserDataRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class JpaUserDetailsService implements UserDetailsService {
private final UserDataRepository userDataRepository;

@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDataEntity user = userDataRepository.findUserDataEntityByUserId(username.toLowerCase()).orElseThrow(
() -> new UsernameNotFoundException("User not found")
);
return new User(user.getUserId(), user.getPassword(), List.of(
user.isAdmin() ? new SimpleGrantedAuthority(Constants.AUTHORITY_ADMIN) : new SimpleGrantedAuthority(Constants.AUTHORITY_GUEST)
));
}
}
65 changes: 65 additions & 0 deletions src/main/java/kr/easw/lesson07/auth/JwtFilterChain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package kr.easw.lesson07.auth;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import kr.easw.lesson07.service.JwtService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@RequiredArgsConstructor
@Component
public class JwtFilterChain extends OncePerRequestFilter {
private final JwtService jwtService;

private final JpaUserDetailsService userDetailsService;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 만약 Authorization 헤더가 없다면, 필터 체인을 계속 진행합니다.
if (request.getHeader("Authorization") == null) {
filterChain.doFilter(request, response);
return;
}
System.out.println("Jwt filter chain");
String token = request.getHeader("Authorization");
System.out.println("Token: " + token);
// 토큰을 검증합니다.
switch (jwtService.validate(token)) {
case VALID:
// 토큰이 유효하다면, 토큰에서 유저 이름을 추출합니다.
String userName = jwtService.extractUsername(token);
// 유저 이름을 통해 유저 정보를 가져옵니다.
UserDetails details = userDetailsService.loadUserByUsername(userName);
System.out.println(details.getAuthorities());
// 유저 정보를 통해 인증 객체를 생성합니다.
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
details,
details.getPassword(),
details.getAuthorities()
));
System.out.println("Token validated / Role: " + details.getAuthorities());
// 필터 체인을 계속 진행합니다.
filterChain.doFilter(request, response);
return;
case EXPIRED:
response.sendError(401, "Expired token");
break;
case UNSUPPORTED:
response.sendError(401, "Unsupported token");
break;
case INVALID:
response.sendError(401, "Invalid token");
break;
}
System.out.println("Token invalid");
System.out.println(jwtService.validate(token));
}
}
Loading