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

refactor/#156 api 인가처리 #161

Merged
merged 9 commits into from
Jan 6, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.springframework.http.HttpStatus.NO_CONTENT;

import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -25,6 +26,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/abouts")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "About", description = "소개글 관리자 API")
public class AboutAdminController {
private final AboutAdminFacade aboutAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.springframework.http.HttpStatus.CREATED;

import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -27,6 +28,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/clubs")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "Club", description = "동아리 관리자 API")
public class ClubAdminController {
private final ClubAdminFacade clubAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kgu.developers.admin.comment.presentation;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -10,6 +11,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/comments")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "Comment", description = "댓글 관리자 API")
public class CommentAdminController {
private final CommentAdminFacade commentAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;

import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand All @@ -28,6 +29,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/files")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "File", description = "파일 업로드 관리 API")
public class FileAdminController {
private final FileAdminFacade fileAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.springframework.http.HttpStatus.CREATED;

import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -27,6 +28,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/labs")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "Lab", description = "연구실 관리자 API")
public class LabAdminController {
private final LabAdminFacade labAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.springframework.http.HttpStatus.CREATED;

import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -28,6 +29,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/posts")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "Post", description = "게시글 관리자 API")
public class PostAdminController {
private final PostAdminFacade postAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.springframework.http.HttpStatus.CREATED;

import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -27,6 +28,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/professors")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "Professor", description = "교수 관리자 API")
public class ProfessorAdminController {
private final ProfessorAdminFacade professorAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.data.domain.PageRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand All @@ -22,6 +23,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/users")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "User", description = "회원 관리자 API")
public class UserAdminController {
private final UserAdminFacade userAdminFacade;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package kgu.developers.api.auth.application;

import java.time.Duration;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import kgu.developers.api.auth.presentation.exception.TokenNotFoundException;
import kgu.developers.api.auth.presentation.request.LoginRequest;
import kgu.developers.api.auth.presentation.request.RefreshTokenRequest;
Expand All @@ -17,6 +11,11 @@
import kgu.developers.domain.user.domain.User;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;

@Service
@Builder
Expand All @@ -35,8 +34,9 @@ public TokenResponse login(LoginRequest request) {
User user = userQueryService.getUserById(userId);
user.isPasswordMatching(password, passwordEncoder);

String refreshToken = tokenProvider.generateToken(user.getId(), Duration.ofDays(1));
String accessToken = tokenProvider.generateToken(user.getId(), Duration.ofHours(1));
String role = user.getRole().name();
String refreshToken = tokenProvider.generateToken(user.getId(), Duration.ofDays(1), role);
String accessToken = tokenProvider.generateToken(user.getId(), Duration.ofHours(1), role);

refreshTokenRepository.save(RefreshToken.of(userId, refreshToken));
return TokenResponse.of(accessToken, refreshToken);
Expand All @@ -50,8 +50,10 @@ public TokenResponse reissue(RefreshTokenRequest request) {
refreshTokenRepository.delete(refreshTokenEntity);

String userId = refreshTokenEntity.getUserId();
String refreshToken = tokenProvider.generateToken(userId, Duration.ofDays(1));
String accessToken = tokenProvider.generateToken(userId, Duration.ofHours(1));
User user = userQueryService.getUserById(userId);
String role = user.getRole().name();
String refreshToken = tokenProvider.generateToken(userId, Duration.ofDays(1), role);
String accessToken = tokenProvider.generateToken(userId, Duration.ofHours(1), role);
refreshTokenRepository.save(RefreshToken.of(userId, refreshToken));
return TokenResponse.of(accessToken, refreshToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,79 +4,89 @@
import static io.jsonwebtoken.SignatureAlgorithm.HS256;
import static javax.xml.crypto.dsig.SignatureProperties.TYPE;

import java.time.Duration;
import java.util.Collections;
import java.util.Date;
import java.util.Set;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import java.time.Duration;
import java.util.Collections;
import java.util.Date;
import java.util.Set;

@Service
@Builder
@RequiredArgsConstructor
public class TokenProvider {
private final JwtProperties jwtProperties;
private final JwtProperties jwtProperties;

public String generateToken(String userId, Duration expiredAt, String role) {
Date now = new Date();
return makeToken(new Date(now.getTime() + expiredAt.toMillis()), userId, role);
}

private String makeToken(Date expiry, String userId, String role) {
Date now = new Date();
return Jwts.builder()
.setHeaderParam(TYPE, JWT_TYPE)
.setIssuer(jwtProperties.getIssuer())
.setIssuedAt(now)
.setExpiration(expiry)
.setSubject(userId)
.claim("userId", userId)
.claim("role", role)
.signWith(HS256, jwtProperties.getSecretKey())
.compact();
}

public String generateToken(String userId, Duration expiredAt) {
Date now = new Date();
return makeToken(new Date(now.getTime() + expiredAt.toMillis()), userId);
}
public boolean validateToken(String token) {
try {
Jwts.parser()
.setSigningKey(jwtProperties.getSecretKey())
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}

private String makeToken(Date expiry, String userId) {
Date now = new Date();
return Jwts.builder()
.setHeaderParam(TYPE, JWT_TYPE)
.setIssuer(jwtProperties.getIssuer())
.setIssuedAt(now)
.setExpiration(expiry)
.setSubject(userId)
.claim("userId", userId)
.signWith(HS256, jwtProperties.getSecretKey())
.compact();
}
public Authentication getAuthentication(String token) {
Claims claims = getClaims(token);
String role = claims.get("role", String.class);
Set<SimpleGrantedAuthority> authorities = getRoles(role);

public boolean validateToken(String token) {
try {
Jwts.parser()
.setSigningKey(jwtProperties.getSecretKey())
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
return new UsernamePasswordAuthenticationToken(
new org.springframework.security.core.userdetails.User(
claims.getSubject(),
"",
authorities
), token, authorities
);
}

public Authentication getAuthentication(String token) {
Claims claims = getClaims(token);
Set<SimpleGrantedAuthority> authorities = Collections.singleton(
new SimpleGrantedAuthority("ROLE_USER")
);
return new UsernamePasswordAuthenticationToken(
new org.springframework.security.core.userdetails.User(
claims.getSubject(),
"",
authorities
), token, authorities
);
}
public Set<SimpleGrantedAuthority> getRoles(String role) {
if (role.equals("ADMIN")) {
return Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
if (role.equals("SUPER")) {
return Collections.singleton(new SimpleGrantedAuthority("ROLE_SUPER"));
}
return Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"));
}

public String getUserId(String token) {
Claims claims = getClaims(token);
return claims.get("userId", String.class);
}
public String getUserId(String token) {
Claims claims = getClaims(token);
return claims.get("userId", String.class);
}

private Claims getClaims(String token) {
return Jwts.parser()
.setSigningKey(jwtProperties.getSecretKey())
.parseClaimsJws(token)
.getBody();
}
private Claims getClaims(String token) {
return Jwts.parser()
.setSigningKey(jwtProperties.getSecretKey())
.parseClaimsJws(token)
.getBody();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
"/api/v1/auth/**",
"/api/v1/professors",
"/api/v1/abouts",
"/api/v1/clubs"
"/api/v1/clubs",
"/api/v1/posts/**",
"/api/v1/labs",
"/api/v1/comments",
};

CorsConfigurationSource corsConfigurationSource() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package kgu.developers.domain.user.domain;
package kgu.developers.common.domain;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum Role {
public enum BaseRole {

USER("일반사용자"),
ADMIN("관리자"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package kgu.developers.common.exception;

import static org.springframework.http.HttpStatus.FORBIDDEN;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum AdminExceptionCode implements ExceptionCode {
NOT_ADMIN(FORBIDDEN, "관리자 전용 API입니다."),
;

private final HttpStatus status;
private final String message;


@Override
public String getCode() {
return this.name();
}
}
Loading
Loading