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

[HOTFIX] #227 - 권한 체크를 위한 로그 추가 #228

Merged
merged 2 commits into from
Oct 5, 2024
Merged
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
16 changes: 8 additions & 8 deletions .github/workflows/dev-CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ jobs:
docker build -f Dockerfile-dev --platform linux/amd64 -t hoonyworld/beat-dev .
docker push hoonyworld/beat-dev

# Trigger Jenkins job - Jenkins 작업 트리거
- name: Trigger Jenkins job
uses: appleboy/jenkins-action@master
with:
url: ${{ secrets.DEV_WEBHOOK_URL }}
user: "beat"
token: ${{ secrets.DEV_JENKINS_API_TOKEN }}
job: "beat-project"
# # Trigger Jenkins job - Jenkins 작업 트리거
# - name: Trigger Jenkins job
# uses: appleboy/jenkins-action@master
# with:
# url: ${{ secrets.DEV_WEBHOOK_URL }}
# user: "beat"
# token: ${{ secrets.DEV_JENKINS_API_TOKEN }}
# job: "beat-project"
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,43 @@
import com.beat.domain.user.domain.Role;
import com.beat.domain.user.domain.Users;
import com.beat.global.auth.client.dto.MemberInfoResponse;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class MemberRegistrationService {

private final UserRepository userRepository;
private final MemberRepository memberRepository;

@Transactional
public Long registerMemberWithUserInfo(final MemberInfoResponse memberInfoResponse) {
Users users = Users.createWithRole(Role.MEMBER);
users = userRepository.save(users);

Member member = Member.create(
memberInfoResponse.nickname(),
memberInfoResponse.email(),
users,
memberInfoResponse.socialId(),
memberInfoResponse.socialType()
);

memberRepository.save(member);
return member.getId();
}
private final UserRepository userRepository;
private final MemberRepository memberRepository;

@Transactional
public Long registerMemberWithUserInfo(final MemberInfoResponse memberInfoResponse) {
Users users = Users.createWithRole(Role.MEMBER);

log.info("Granting MEMBER role to new user with role: {}", users.getRole());

users = userRepository.save(users);

log.info("Registering new user with role: {}", users.getRole());

Member member = Member.create(
memberInfoResponse.nickname(),
memberInfoResponse.email(),
users,
memberInfoResponse.socialId(),
memberInfoResponse.socialType()
);

memberRepository.save(member);

log.info("Member registered with memberId: {}, role: {}", member.getId(), users.getRole());

return member.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
import com.beat.global.auth.jwt.provider.JwtValidationType;
import com.beat.global.auth.security.AdminAuthentication;
import com.beat.global.auth.security.MemberAuthentication;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
Expand All @@ -29,77 +32,81 @@
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final JwtTokenProvider jwtTokenProvider;

@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {

final String token = getJwtFromRequest(request);

if (!StringUtils.hasText(token)) {
log.info("JWT Token not found in request header. Assuming guest access or public API request.");
filterChain.doFilter(request, response);
return;
}

try {
JwtValidationType validationType = jwtTokenProvider.validateToken(token);

if (validationType == JwtValidationType.VALID_JWT) {
setAuthentication(token, request);
filterChain.doFilter(request, response);
} else {
handleInvalidToken(validationType, response);
}
} catch (Exception e) {
log.error("JWT Authentication Exception: ", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 응답
}
}

private void setAuthentication(String token, HttpServletRequest request) {
Long memberId = jwtTokenProvider.getMemberIdFromJwt(token);
Role role = jwtTokenProvider.getRoleFromJwt(token);

Collection<GrantedAuthority> authorities = List.of(role.toGrantedAuthority());
UsernamePasswordAuthenticationToken authentication = createAuthentication(memberId, authorities, role);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

SecurityContextHolder.getContext().setAuthentication(authentication);
log.info("Authentication set for memberId: {}, role: {}", memberId, role);
}

private void handleInvalidToken(JwtValidationType validationType, HttpServletResponse response) {
if (validationType == JwtValidationType.EXPIRED_JWT_TOKEN) {
log.warn("JWT Token is expired");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 응답
} else {
log.warn("JWT Token is invalid");
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400 응답
}
}

private UsernamePasswordAuthenticationToken createAuthentication(Long memberId, Collection<GrantedAuthority> authorities, Role role) {
log.info("Creating authentication for memberId: {} with role: {}", memberId, role);

if (role == Role.ADMIN) {
log.info("Creating AdminAuthentication for memberId: {}", memberId);
return new AdminAuthentication(memberId.toString(), null, authorities);
} else if (role == Role.MEMBER) {
log.info("Creating MemberAuthentication for memberId: {}", memberId);
return new MemberAuthentication(memberId.toString(), null, authorities);
}
log.error("Unknown role: {}", role);
throw new IllegalArgumentException("Unknown role: " + role);
}

private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring("Bearer ".length());
}
return null;
}
private final JwtTokenProvider jwtTokenProvider;

@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {

final String token = getJwtFromRequest(request);

if (!StringUtils.hasText(token)) {
log.info("JWT Token not found in request header. Assuming guest access or public API request.");
filterChain.doFilter(request, response);
return;
}

try {
JwtValidationType validationType = jwtTokenProvider.validateToken(token);

if (validationType == JwtValidationType.VALID_JWT) {
setAuthentication(token, request);
filterChain.doFilter(request, response);
} else {
handleInvalidToken(validationType, response);
}
} catch (Exception e) {
log.error("JWT Authentication Exception: ", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 응답
}
}

private void setAuthentication(String token, HttpServletRequest request) {
Long memberId = jwtTokenProvider.getMemberIdFromJwt(token);
Role role = jwtTokenProvider.getRoleFromJwt(token);

log.info("Setting authentication for memberId: {} with role: {}", memberId, role);

Collection<GrantedAuthority> authorities = List.of(role.toGrantedAuthority());
UsernamePasswordAuthenticationToken authentication = createAuthentication(memberId, authorities, role);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

log.info("Authentication set: memberId: {}, role: {}", memberId, role);

SecurityContextHolder.getContext().setAuthentication(authentication);
}

private void handleInvalidToken(JwtValidationType validationType, HttpServletResponse response) {
if (validationType == JwtValidationType.EXPIRED_JWT_TOKEN) {
log.warn("JWT Token is expired");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 응답
} else {
log.warn("JWT Token is invalid");
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400 응답
}
}

private UsernamePasswordAuthenticationToken createAuthentication(Long memberId,
Collection<GrantedAuthority> authorities, Role role) {
log.info("Creating authentication for memberId: {} with role: {}", memberId, role);

if (role == Role.ADMIN) {
log.info("Creating AdminAuthentication for memberId: {}", memberId);
return new AdminAuthentication(memberId.toString(), null, authorities);
} else if (role == Role.MEMBER) {
log.info("Creating MemberAuthentication for memberId: {}", memberId);
return new MemberAuthentication(memberId.toString(), null, authorities);
}
log.error("Unknown role: {}", role);
throw new IllegalArgumentException("Unknown role: " + role);
}

private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring("Bearer ".length());
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,21 @@ public String issueRefreshToken(final Authentication authentication) {
private String issueToken(final Authentication authentication, final long expiredTime) {
final Date now = new Date();

final Claims claims = Jwts.claims()
.setIssuedAt(now)
.setExpiration(new Date(now.getTime() + expiredTime));
final Claims claims = Jwts.claims().setIssuedAt(now).setExpiration(new Date(now.getTime() + expiredTime));

claims.put(MEMBER_ID, authentication.getPrincipal());
claims.put(ROLE_KEY, authentication.getAuthorities().stream()

log.info("Authorities before token generation: {}", authentication.getAuthorities());

String role = authentication.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No authorities found for user")));
.orElseThrow(() -> new IllegalArgumentException("No authorities found for user"));

log.info("Selected role for token: {}", role);

claims.put(ROLE_KEY, role);

return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
Expand Down Expand Up @@ -102,11 +108,7 @@ public JwtValidationType validateToken(String token) {
}

private Claims getBody(final String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
return Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();
}

public Long getMemberIdFromJwt(String token) {
Expand All @@ -123,9 +125,11 @@ public Role getRoleFromJwt(String token) {
Claims claims = getBody(token);
String roleName = claims.get(ROLE_KEY, String.class);

log.info("Extracted role from JWT: {}", roleName);

// "ROLE_" 접두사 제거
String enumValue = roleName.replace("ROLE_", "");
log.info("Extracted role from JWT: {}", enumValue);
log.info("Final role after processing: {}", enumValue);

return Role.valueOf(enumValue.toUpperCase());
}
Expand Down
Loading