-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from Kusitms-28th-Meetup-D/feature/7-security
카카오 소셜로그인, 시큐리티를 통한 인가 인증
- Loading branch information
Showing
38 changed files
with
996 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
src/main/java/com/kusithm/meetupd/common/auth/AuthConstants.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.kusithm.meetupd.common.auth; | ||
|
||
public final class AuthConstants { | ||
public static final String AUTH_HEADER = "Authorization"; | ||
public static final String TOKEN_TYPE = "Bearer "; | ||
} |
26 changes: 26 additions & 0 deletions
26
src/main/java/com/kusithm/meetupd/common/auth/CustomAuthenticationEntryPoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.kusithm.meetupd.common.auth; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.kusithm.meetupd.common.error.ErrorCode; | ||
import com.kusithm.meetupd.common.error.dto.ErrorResponse; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.web.AuthenticationEntryPoint; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.io.IOException; | ||
|
||
@Component | ||
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { | ||
private final ObjectMapper objectMapper = new ObjectMapper(); | ||
@Override | ||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { | ||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); | ||
response.setCharacterEncoding("utf-8"); | ||
response.setStatus(ErrorCode.UNAUTHORIZED.getStatus().value()); | ||
response.getWriter().write(objectMapper.writeValueAsString(ErrorResponse.of(ErrorCode.UNAUTHORIZED))); | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
src/main/java/com/kusithm/meetupd/common/auth/ExceptionHandlerFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package com.kusithm.meetupd.common.auth; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.kusithm.meetupd.common.error.ErrorCode; | ||
import com.kusithm.meetupd.common.error.ForbiddenException; | ||
import com.kusithm.meetupd.common.error.UnauthorizedException; | ||
import com.kusithm.meetupd.common.error.dto.ErrorResponse; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import java.io.IOException; | ||
|
||
@Slf4j | ||
public class ExceptionHandlerFilter extends OncePerRequestFilter { | ||
private final ObjectMapper objectMapper = new ObjectMapper(); | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
try { | ||
filterChain.doFilter(request, response); | ||
} catch (UnauthorizedException e) { | ||
handleUnauthorizedException(response, e); | ||
} catch (ForbiddenException e) { | ||
handleForbiddenException(response, e); | ||
} catch (Exception ee) { | ||
handleException(response); | ||
} | ||
} | ||
|
||
private void handleUnauthorizedException(HttpServletResponse response, Exception e) throws IOException { | ||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); | ||
response.setCharacterEncoding("utf-8"); | ||
if (e instanceof UnauthorizedException ue) { | ||
response.setStatus(ue.getError().getStatus().value());; | ||
response.getWriter().write(objectMapper.writeValueAsString(ErrorResponse.of(ue.getError()))); | ||
} | ||
} | ||
|
||
|
||
private void handleForbiddenException(HttpServletResponse response, Exception e) throws IOException { | ||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); | ||
response.setCharacterEncoding("utf-8"); | ||
if (e instanceof ForbiddenException fe) { | ||
response.setStatus(fe.getError().getStatus().value());; | ||
response.getWriter().write(objectMapper.writeValueAsString(ErrorResponse.of(fe.getError()))); | ||
} | ||
} | ||
|
||
private void handleException(HttpServletResponse response) throws IOException { | ||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); | ||
response.setCharacterEncoding("utf-8"); | ||
response.setStatus(ErrorCode.INTERNAL_SERVER_ERROR.getStatus().value()); | ||
response.getWriter().write(objectMapper.writeValueAsString(ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR))); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
src/main/java/com/kusithm/meetupd/common/auth/JwtAuthenticationFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.kusithm.meetupd.common.auth; | ||
|
||
import com.kusithm.meetupd.common.error.ErrorCode; | ||
import com.kusithm.meetupd.common.error.ForbiddenException; | ||
import com.kusithm.meetupd.common.jwt.TokenProvider; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | ||
import org.springframework.util.StringUtils; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import java.io.IOException; | ||
|
||
@RequiredArgsConstructor | ||
public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||
|
||
private final TokenProvider tokenProvider; | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
String accessToken = getAccessTokenFromHttpServletRequest(request); | ||
tokenProvider.validateAccessToken(accessToken); | ||
Long userId = tokenProvider.getTokenSubject(accessToken); | ||
setAuthentication(request, userId); | ||
filterChain.doFilter(request, response); | ||
} | ||
|
||
|
||
private String getAccessTokenFromHttpServletRequest(HttpServletRequest request) { | ||
String accessToken = request.getHeader(AuthConstants.AUTH_HEADER); | ||
if (StringUtils.hasText(accessToken) && accessToken.startsWith(AuthConstants.TOKEN_TYPE)) { | ||
return accessToken.split(" ")[1]; | ||
} | ||
throw new ForbiddenException(ErrorCode.UNAUTHORIZED); | ||
} | ||
|
||
|
||
private void setAuthentication(HttpServletRequest request, Long userId) { | ||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userId, null, null); | ||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.kusithm.meetupd.common.auth; | ||
|
||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/* | ||
@Target(ElementType.PARAMETER) | ||
Annotation 을 생성할 수 있는 위치를 지정 | ||
PARAMETER 로 지정했으니 메소드의 파라미터로 선언된 객체에서만 사용할 수 있다. | ||
@Retention(RetentionPolicy.RUNTIME) | ||
Annotation 의 라이프 사이크를 지정 | ||
SOURCE vs CLASS vs RUNTIME | ||
소스코드까지 | 바이트코드까지 | 런타임까지(안 사라진다) | ||
*/ | ||
@Target(ElementType.PARAMETER) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface UserId { | ||
} |
27 changes: 27 additions & 0 deletions
27
src/main/java/com/kusithm/meetupd/common/auth/UserIdArgumentResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.kusithm.meetupd.common.auth; | ||
|
||
import org.springframework.core.MethodParameter; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
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; | ||
|
||
@Component | ||
public class UserIdArgumentResolver implements HandlerMethodArgumentResolver { | ||
|
||
@Override | ||
public boolean supportsParameter(MethodParameter parameter) { | ||
boolean hasUserIdAnnotation = parameter.hasParameterAnnotation(UserId.class); | ||
boolean hasLongType = Long.class.isAssignableFrom(parameter.getParameterType()); | ||
return hasUserIdAnnotation && hasLongType; | ||
} | ||
|
||
@Override | ||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { | ||
return SecurityContextHolder.getContext() | ||
.getAuthentication() | ||
.getPrincipal(); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/com/kusithm/meetupd/common/config/FeignClientConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.kusithm.meetupd.common.config; | ||
|
||
import com.kusithm.meetupd.MeetupDApplication; | ||
import org.springframework.cloud.openfeign.EnableFeignClients; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@EnableFeignClients(basePackageClasses = MeetupDApplication.class) | ||
@Configuration | ||
public class FeignClientConfig { | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/com/kusithm/meetupd/common/config/SecurityConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.kusithm.meetupd.common.config; | ||
|
||
import com.kusithm.meetupd.common.auth.CustomAuthenticationEntryPoint; | ||
import com.kusithm.meetupd.common.auth.ExceptionHandlerFilter; | ||
import com.kusithm.meetupd.common.auth.JwtAuthenticationFilter; | ||
import com.kusithm.meetupd.common.jwt.TokenProvider; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; | ||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; | ||
import org.springframework.security.config.http.SessionCreationPolicy; | ||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
@RequiredArgsConstructor | ||
@Configuration | ||
@EnableWebSecurity | ||
public class SecurityConfig { | ||
|
||
private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; | ||
private final TokenProvider tokenProvider; | ||
|
||
// TODO api 추가될 때 white list url 확인해서 추가하기. | ||
private static final String[] WHITE_LIST_URL = {"/api/health","/api/auth/register","/api/auth/login", "/api/auth/reissue", "/"}; | ||
|
||
@Bean | ||
public WebSecurityCustomizer webSecurityCustomizer() { | ||
return (web) -> web.ignoring().requestMatchers(WHITE_LIST_URL); | ||
} | ||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
return http | ||
.formLogin(AbstractHttpConfigurer::disable) | ||
.httpBasic(AbstractHttpConfigurer::disable) | ||
.csrf(AbstractHttpConfigurer::disable) | ||
.sessionManagement((sessionManagement) -> | ||
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) | ||
// .exceptionHandling(exceptionHandlingConfigurer -> | ||
// exceptionHandlingConfigurer.authenticationEntryPoint(customAuthenticationEntryPoint)) | ||
.addFilterBefore(new JwtAuthenticationFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) | ||
.addFilterBefore(new ExceptionHandlerFilter(), JwtAuthenticationFilter.class) | ||
.build(); | ||
} | ||
|
||
@Bean | ||
public PasswordEncoder getPasswordEncoder() { | ||
return new BCryptPasswordEncoder(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 2 additions & 3 deletions
5
src/main/java/com/kusithm/meetupd/common/error/ApplicationException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,13 @@ | ||
package com.kusithm.meetupd.common.error; | ||
|
||
import lombok.Getter; | ||
import org.springframework.http.HttpStatus; | ||
|
||
@Getter | ||
public class ApplicationException extends RuntimeException { | ||
private final HttpStatus status; | ||
private final ErrorCode error; | ||
|
||
public ApplicationException(ErrorCode error) { | ||
super(error.getMessage()); | ||
this.status = error.getStatus(); | ||
this.error = error; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/com/kusithm/meetupd/common/error/ForbiddenException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.kusithm.meetupd.common.error; | ||
|
||
public class ForbiddenException extends ApplicationException{ | ||
public ForbiddenException(ErrorCode error) { | ||
super(error); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/kusithm/meetupd/common/error/UnauthorizedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.kusithm.meetupd.common.error; | ||
|
||
public class UnauthorizedException extends ApplicationException{ | ||
public UnauthorizedException(ErrorCode error) { | ||
super(error); | ||
} | ||
} |
Oops, something went wrong.