-
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.
* feat: Security 기본 설정 * feat: oAuth구성요소 기본설정 * feat: oAuth Login * feat: Jwt Generator * feat: Token 발행 * fix: 불필요한 코드 삭제 * fix: 불필요한 코드 삭제 * fix: 프론트 기본 URL로 변경 * fix: 불필요한 코드 삭제 * fix: yml 설정분리
- Loading branch information
Showing
31 changed files
with
743 additions
and
13 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
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
67 changes: 67 additions & 0 deletions
67
core-api/src/main/java/com/imlinker/coreapi/configuration/SecurityConfiguration.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,67 @@ | ||
package com.imlinker.coreapi.configuration; | ||
|
||
import com.imlinker.coreapi.core.auth.jwt.JwtTokenProperties; | ||
import com.imlinker.coreapi.core.auth.jwt.TokenProperties; | ||
import com.imlinker.coreapi.core.auth.oauth2.*; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
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.web.SecurityFilterChain; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
@RequiredArgsConstructor | ||
@EnableConfigurationProperties({JwtTokenProperties.class, TokenProperties.class}) | ||
public class SecurityConfiguration { | ||
private final CustomOAuth2UserService customOAuth2UserService; | ||
private final CustomAccessDeniedHandler customAccessDeniedHandler; | ||
private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; | ||
private final CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler; | ||
private final CustomAuthorizationRequestResolver customOAuth2AuthorizationRequestResolver; | ||
|
||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
http.cors(AbstractHttpConfigurer::disable) | ||
.csrf(AbstractHttpConfigurer::disable) | ||
.httpBasic(AbstractHttpConfigurer::disable); | ||
|
||
http.oauth2Login( | ||
loginHandler -> | ||
loginHandler | ||
.successHandler(customAuthenticationSuccessHandler) | ||
.userInfoEndpoint( | ||
userInfoEndpoint -> userInfoEndpoint.userService(customOAuth2UserService)) | ||
.authorizationEndpoint( | ||
authorizationEndpoint -> | ||
authorizationEndpoint.authorizationRequestResolver( | ||
customOAuth2AuthorizationRequestResolver))); | ||
|
||
http.exceptionHandling( | ||
exceptionHandling -> | ||
exceptionHandling | ||
.accessDeniedHandler(customAccessDeniedHandler) | ||
.authenticationEntryPoint(customAuthenticationEntryPoint)); | ||
|
||
http.authorizeHttpRequests(authorizeRequests -> authorizeRequests.anyRequest().permitAll()); | ||
|
||
return http.build(); | ||
} | ||
|
||
@Bean | ||
public WebSecurityCustomizer webSecurityCustomizer() { | ||
return (web) -> | ||
web.ignoring() | ||
.requestMatchers( | ||
"/v3/api-docs/**", | ||
"/swagger-resources/**", | ||
"/swagger-ui/**", | ||
"/webjars/**", | ||
"/swagger/**", | ||
"/favicon.ico"); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
core-api/src/main/java/com/imlinker/coreapi/core/auth/jwt/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,45 @@ | ||
package com.imlinker.coreapi.core.auth.jwt; | ||
|
||
import com.imlinker.coreapi.support.exception.FilterExceptionHandler; | ||
import com.imlinker.error.ErrorType; | ||
import io.jsonwebtoken.Claims; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.ServletRequest; | ||
import jakarta.servlet.ServletResponse; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import lombok.AllArgsConstructor; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.web.filter.GenericFilterBean; | ||
|
||
@AllArgsConstructor | ||
public class JwtAuthenticationFilter extends GenericFilterBean { | ||
|
||
private final JwtTokenProvider jwtTokenProvider; | ||
private final FilterExceptionHandler filterExceptionHandler; | ||
|
||
@Override | ||
public void doFilter( | ||
ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) | ||
throws IOException, ServletException { | ||
try { | ||
String token = ((HttpServletRequest) servletRequest).getHeader("Authorization"); | ||
if (token != null) { | ||
Claims claims = | ||
jwtTokenProvider.parseClaims(token.replace("Bearer ", ""), TokenType.ACCESS_TOKEN); | ||
if (claims != null) { | ||
SecurityContextHolder.getContext() | ||
.setAuthentication(jwtTokenProvider.generateAuthentication(claims)); | ||
} | ||
} | ||
|
||
filterChain.doFilter(servletRequest, servletResponse); | ||
} catch (Exception e) { | ||
filterExceptionHandler.sendErrorMessage( | ||
(HttpServletResponse) servletResponse, ErrorType.INTERNAL_PROCESSING_ERROR, e.getCause()); | ||
} | ||
filterChain.doFilter(servletRequest, servletResponse); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
core-api/src/main/java/com/imlinker/coreapi/core/auth/jwt/JwtTokenProperties.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,21 @@ | ||
package com.imlinker.coreapi.core.auth.jwt; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
@ConfigurationProperties(prefix = "jwt") | ||
public class JwtTokenProperties { | ||
private final TokenProperties access; | ||
private final TokenProperties refresh; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public static class TokenProperties { | ||
private final Long expire; | ||
private final String secret; | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
core-api/src/main/java/com/imlinker/coreapi/core/auth/jwt/JwtTokenProvider.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,73 @@ | ||
package com.imlinker.coreapi.core.auth.jwt; | ||
|
||
import com.imlinker.coreapi.support.exception.FilterExceptionHandler; | ||
import com.imlinker.domain.common.Email; | ||
import com.imlinker.error.ApplicationException; | ||
import com.imlinker.error.ErrorType; | ||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.ExpiredJwtException; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.MalformedJwtException; | ||
import io.jsonwebtoken.io.DecodingException; | ||
import io.jsonwebtoken.security.Keys; | ||
import java.time.Instant; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.Date; | ||
import javax.crypto.SecretKey; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class JwtTokenProvider { | ||
|
||
private final JwtTokenProperties jwtTokenProperties; | ||
private final FilterExceptionHandler filterExceptionHandler; | ||
|
||
public String generateToken(Email email, TokenType tokenType) { | ||
JwtTokenProperties.TokenProperties properties = | ||
tokenType == TokenType.ACCESS_TOKEN | ||
? jwtTokenProperties.getAccess() | ||
: jwtTokenProperties.getRefresh(); | ||
|
||
Instant now = Instant.now(); | ||
Instant expire = now.plus(properties.getExpire(), ChronoUnit.MILLIS); | ||
|
||
return Jwts.builder() | ||
.claim("email", email.getValue()) | ||
.setIssuedAt(Date.from(now)) | ||
.setExpiration(Date.from(expire)) | ||
.signWith(Keys.hmacShaKeyFor(properties.getSecret().getBytes())) | ||
.compact(); | ||
} | ||
|
||
public Claims parseClaims(String token, TokenType tokenType) { | ||
try { | ||
SecretKey key = | ||
Keys.hmacShaKeyFor( | ||
(tokenType == TokenType.ACCESS_TOKEN | ||
? jwtTokenProperties.getAccess() | ||
: jwtTokenProperties.getRefresh()) | ||
.getSecret() | ||
.getBytes()); | ||
|
||
return Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody(); | ||
|
||
} catch (SecurityException e) { | ||
throw new ApplicationException(ErrorType.UNAUTHORIZED, "유효하지 않은 토큰입니다.", e.getCause()); | ||
} catch (ExpiredJwtException e) { | ||
throw new ApplicationException(ErrorType.UNAUTHORIZED, "만료된 토큰입니다.", e.getCause()); | ||
} catch (DecodingException e) { | ||
throw new ApplicationException(ErrorType.UNAUTHORIZED, "잘못된 인증입니다.", e.getCause()); | ||
} catch (MalformedJwtException e) { | ||
throw new ApplicationException(ErrorType.UNAUTHORIZED, "손상된 토큰입니다.", e.getCause()); | ||
} | ||
} | ||
|
||
public Authentication generateAuthentication(Claims claims) { | ||
Email email = Email.of(claims.get("email").toString()); | ||
return new UsernamePasswordAuthenticationToken(email, null, null); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
core-api/src/main/java/com/imlinker/coreapi/core/auth/jwt/TokenProperties.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,13 @@ | ||
package com.imlinker.coreapi.core.auth.jwt; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
@ConfigurationProperties(prefix = "token") | ||
public class TokenProperties { | ||
private final Long expire; | ||
private final String secret; | ||
} |
6 changes: 6 additions & 0 deletions
6
core-api/src/main/java/com/imlinker/coreapi/core/auth/jwt/TokenType.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.imlinker.coreapi.core.auth.jwt; | ||
|
||
public enum TokenType { | ||
ACCESS_TOKEN, | ||
REFRESH_TOKEN | ||
} |
28 changes: 28 additions & 0 deletions
28
core-api/src/main/java/com/imlinker/coreapi/core/auth/oauth2/CustomAccessDeniedHandler.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,28 @@ | ||
package com.imlinker.coreapi.core.auth.oauth2; | ||
|
||
import com.imlinker.coreapi.support.exception.FilterExceptionHandler; | ||
import com.imlinker.error.ErrorType; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.access.AccessDeniedException; | ||
import org.springframework.security.web.access.AccessDeniedHandler; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class CustomAccessDeniedHandler implements AccessDeniedHandler { | ||
|
||
private final FilterExceptionHandler filterExceptionHandler; | ||
|
||
@Override | ||
public void handle( | ||
HttpServletRequest request, | ||
HttpServletResponse response, | ||
AccessDeniedException accessDeniedException) | ||
throws IOException { | ||
filterExceptionHandler.sendErrorMessage( | ||
response, ErrorType.UNAUTHORIZED, accessDeniedException); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...i/src/main/java/com/imlinker/coreapi/core/auth/oauth2/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,27 @@ | ||
package com.imlinker.coreapi.core.auth.oauth2; | ||
|
||
import com.imlinker.coreapi.support.exception.FilterExceptionHandler; | ||
import com.imlinker.error.ErrorType; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.web.AuthenticationEntryPoint; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { | ||
|
||
private final FilterExceptionHandler filterExceptionHandler; | ||
|
||
@Override | ||
public void commence( | ||
HttpServletRequest request, | ||
HttpServletResponse response, | ||
AuthenticationException authException) | ||
throws IOException { | ||
filterExceptionHandler.sendErrorMessage(response, ErrorType.UNAUTHENTICATED, authException); | ||
} | ||
} |
Oops, something went wrong.