-
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.
Browse files
Browse the repository at this point in the history
* chore: Spring Security gradle 추가 * feat: User 도메인 정보 추가 - email, password, role, socialEmail 추가 * feat: PrincipalDetail 설정 - 인증과 권한 부여를 위해 사용자 정보를 캡슐화 * feat: 시큐리티 필터 설정 및 JWT 개발 * feat: refreshToken 개발 * feat: JWT Provider 개발 * refactor: BaseEntity 변경 * refactor: School 도메인 리펙토링 * feat: School Repositroy, mapper 개발 * feat: Profile Repositroy, mapper 개발 * refactor: Setting, FCM 도메인 수정 * feat: UserConsent 도메인 추가 * refactor: Social 도메인 수정 * refactor: User 도메인 수정 및 Role 추가 * feat: Auth Dto 설정 * refactor: School 도메인 리팩토링 유저와 연결 끊도록 설정 * refactor: RefreshToken create, update 설정 및 서비스 추가 * feat: Redis 모듈 추가, 설정 및 AuthDate 저장 * refactor: DTO 폴더 경로 추가 * feat: SecurityUtils 추가 * feat: AuthService 추가 * feat: Auth Controller 추가 및 url 설정 변경 * refactor: rebase 후 코드 리팩토링 * test: service Test 코드 작성 * fix: baseEntity notnull 조건 제거 * fix: VoteServiceTest 에러 주석 처리 * test: 주석 제거 * chore: 서브모듈에 jwt 추가 * refactor: gitmodules 수정 이후, 이전 backend-submodule 삭제 * refactor: submoudle 이름 config로 변경 * refactor: LocalDateTime.now() 모킹 * refactor: 401에러 예외 메시지 설정, cors 주소, delete에 트랜잭션 추가 * refactor: api prefix 제거 * refactor: refreshToken test에 있는 createdAt 수정 --------- Co-authored-by: jaeyeon kim <[email protected]>
- Loading branch information
Showing
104 changed files
with
2,122 additions
and
253 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
[submodule "app/src/main/resources/backend-submodule"] | ||
path = app/src/main/resources/backend-submodule | ||
url = https://github.com/yapp-wespot/backend-submodule.git | ||
[submodule "app/src/main/resources/config"] | ||
path = app/src/main/resources/config | ||
url = https://github.com/yapp-wespot/config.git |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package com.wespot.auth | ||
|
||
import com.wespot.auth.dto.request.AuthLoginRequest | ||
import com.wespot.auth.dto.request.RefreshTokenRequest | ||
import com.wespot.auth.dto.request.SignUpRequest | ||
import com.wespot.auth.dto.response.SignUpResponse | ||
import com.wespot.auth.dto.response.TokenResponse | ||
import com.wespot.auth.service.AuthService | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.http.ResponseEntity | ||
import org.springframework.web.bind.annotation.PostMapping | ||
import org.springframework.web.bind.annotation.RequestBody | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
@RequestMapping("/v1/auth") | ||
class AuthController( | ||
private val authService: AuthService | ||
) { | ||
|
||
@PostMapping("/login") | ||
fun signIn( | ||
@RequestBody request: AuthLoginRequest | ||
): Any { | ||
|
||
val response = authService.socialAccess(request) | ||
|
||
return if (response is SignUpResponse) { | ||
ResponseEntity.status(HttpStatus.ACCEPTED).body(response) | ||
} else { | ||
ResponseEntity.ok() | ||
.body(response) | ||
} | ||
|
||
} | ||
|
||
@PostMapping("/signup") | ||
fun signUp( | ||
@RequestBody request: SignUpRequest | ||
): ResponseEntity<TokenResponse> { | ||
|
||
val signUp = authService.signUp(request) | ||
|
||
return ResponseEntity.ok() | ||
.body(signUp) | ||
|
||
} | ||
|
||
@PostMapping("/reissue") | ||
fun reissue( | ||
@RequestBody request: RefreshTokenRequest | ||
): ResponseEntity<TokenResponse> { | ||
|
||
val response = authService.reIssueToken(request) | ||
|
||
return ResponseEntity.ok() | ||
.body(response) | ||
|
||
} | ||
|
||
@PostMapping("/revoke") | ||
fun revoke(): ResponseEntity<Unit> { | ||
|
||
authService.revoke() | ||
|
||
return ResponseEntity.noContent().build() | ||
|
||
} | ||
|
||
} |
76 changes: 76 additions & 0 deletions
76
app/src/main/kotlin/com/wespot/config/security/CustomUrlFilter.kt
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,76 @@ | ||
package com.wespot.config.security | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import jakarta.servlet.FilterChain | ||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.http.MediaType | ||
import org.springframework.http.ProblemDetail | ||
import org.springframework.stereotype.Component | ||
import org.springframework.util.AntPathMatcher | ||
import org.springframework.web.filter.OncePerRequestFilter | ||
import java.net.URI | ||
import kotlin.text.Charsets.UTF_8 | ||
|
||
@Component | ||
class CustomUrlFilter( | ||
private val objectMapper: ObjectMapper | ||
) : OncePerRequestFilter() { | ||
|
||
private val antPathMatcher = AntPathMatcher() | ||
|
||
private val validUrlPatterns = listOf( | ||
"/health", | ||
"/", | ||
"/api/v1/auth/reissue", | ||
"/api/v1/auth/login", | ||
"/api/v1/auth/signup", | ||
"/api/v1/auth/revoke", | ||
) | ||
|
||
override fun doFilterInternal( | ||
request: HttpServletRequest, | ||
response: HttpServletResponse, | ||
filterChain: FilterChain | ||
) { | ||
|
||
if (!isValidUrl(request)) { | ||
handleInvalidUrl(request, response) | ||
return | ||
} | ||
filterChain.doFilter(request, response) | ||
|
||
} | ||
|
||
private fun isValidUrl(request: HttpServletRequest): Boolean { | ||
|
||
val requestUri = request.requestURI | ||
|
||
return validUrlPatterns.any { antPathMatcher.match(it, requestUri) } | ||
|
||
} | ||
|
||
private fun handleInvalidUrl( | ||
request: HttpServletRequest, | ||
response: HttpServletResponse | ||
) { | ||
|
||
response.contentType = MediaType.APPLICATION_JSON_VALUE | ||
response.characterEncoding = UTF_8.name() | ||
response.status = HttpStatus.NOT_FOUND.value() | ||
|
||
val body = objectMapper.writeValueAsString( | ||
ProblemDetail.forStatusAndDetail( | ||
HttpStatus.NOT_FOUND, | ||
NoSuchFieldException("잘못된 URL입니다.").message!!, | ||
).apply { | ||
type = URI.create("/errors/not-found") | ||
instance = URI.create(request.requestURI) | ||
} | ||
) | ||
|
||
response.writer.write(body) | ||
|
||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
app/src/main/kotlin/com/wespot/config/security/JwtAccessDeniedHandler.kt
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,42 @@ | ||
package com.wespot.config.security | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.http.MediaType | ||
import org.springframework.http.ProblemDetail | ||
import org.springframework.security.access.AccessDeniedException | ||
import org.springframework.security.web.access.AccessDeniedHandler | ||
import org.springframework.stereotype.Component | ||
import java.net.URI | ||
import kotlin.text.Charsets.UTF_8 | ||
|
||
@Component | ||
class JwtAccessDeniedHandler( | ||
private val objectMapper: ObjectMapper | ||
) : AccessDeniedHandler { | ||
override fun handle( | ||
request: HttpServletRequest, | ||
response: HttpServletResponse, | ||
exception: AccessDeniedException | ||
) { | ||
|
||
response.contentType = MediaType.APPLICATION_JSON_VALUE | ||
response.characterEncoding = UTF_8.name() | ||
response.status = HttpStatus.FORBIDDEN.value() | ||
|
||
val body = objectMapper.writeValueAsString( | ||
ProblemDetail.forStatusAndDetail( | ||
HttpStatus.UNAUTHORIZED, | ||
AccessDeniedException("자신의 것만 가능합니다").message!!, | ||
).apply { | ||
type = URI.create("/errors/forbidden") | ||
instance = URI.create(request.requestURI) | ||
} | ||
) | ||
response.writer.write(body) | ||
|
||
} | ||
|
||
} |
43 changes: 43 additions & 0 deletions
43
app/src/main/kotlin/com/wespot/config/security/JwtAuthenticationEntryPoint.kt
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,43 @@ | ||
package com.wespot.config.security | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.http.MediaType | ||
import org.springframework.http.ProblemDetail | ||
import org.springframework.security.authentication.BadCredentialsException | ||
import org.springframework.security.core.AuthenticationException | ||
import org.springframework.security.web.AuthenticationEntryPoint | ||
import org.springframework.stereotype.Component | ||
import java.net.URI | ||
import kotlin.text.Charsets.UTF_8 | ||
|
||
@Component | ||
class JwtAuthenticationEntryPoint( | ||
private val objectMapper: ObjectMapper | ||
) : AuthenticationEntryPoint { | ||
override fun commence( | ||
request: HttpServletRequest, | ||
response: HttpServletResponse, | ||
authException: AuthenticationException? | ||
) { | ||
|
||
response.contentType = MediaType.APPLICATION_JSON_VALUE | ||
response.characterEncoding = UTF_8.name() | ||
response.status = HttpStatus.UNAUTHORIZED.value() | ||
|
||
val body = objectMapper.writeValueAsString( | ||
ProblemDetail.forStatusAndDetail( | ||
HttpStatus.UNAUTHORIZED, | ||
BadCredentialsException("로그인이 만료되었습니다. 계속하려면 다시 로그인해 주세요.").message!!, | ||
).apply { | ||
type = URI.create("/errors/unauthenticated") | ||
instance = URI.create(request.requestURI) | ||
} | ||
) | ||
response.writer.write(body) | ||
|
||
} | ||
} | ||
|
52 changes: 52 additions & 0 deletions
52
app/src/main/kotlin/com/wespot/config/security/JwtAuthenticationFilter.kt
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,52 @@ | ||
package com.wespot.config.security | ||
|
||
import com.wespot.auth.JwtTokenInfo | ||
import com.wespot.auth.port.`in`.AuthenticationUseCase | ||
import jakarta.servlet.FilterChain | ||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.springframework.security.authentication.BadCredentialsException | ||
import org.springframework.security.core.context.SecurityContextHolder | ||
import org.springframework.stereotype.Component | ||
import org.springframework.util.StringUtils | ||
import org.springframework.web.filter.OncePerRequestFilter | ||
|
||
@Component | ||
class JwtAuthenticationFilter( | ||
private val authenticationUseCase: AuthenticationUseCase, | ||
private val jwtAuthenticationEntryPoint: JwtAuthenticationEntryPoint, | ||
) : OncePerRequestFilter() { | ||
|
||
override fun doFilterInternal( | ||
request: HttpServletRequest, | ||
response: HttpServletResponse, | ||
filterChain: FilterChain | ||
) { | ||
val token = extractToken(request) | ||
if (token != null && StringUtils.hasText(token)) { | ||
try { | ||
authenticateUserByToken(token) | ||
} catch (e: BadCredentialsException) { | ||
jwtAuthenticationEntryPoint.commence(request, response, authException = null) | ||
return | ||
} | ||
} | ||
filterChain.doFilter(request, response) | ||
} | ||
|
||
private fun authenticateUserByToken(token: String) { | ||
try { | ||
val authentication = authenticationUseCase.getAuthentication(token) | ||
SecurityContextHolder.getContext().authentication = authentication | ||
} catch (e: BadCredentialsException) { | ||
SecurityContextHolder.clearContext() | ||
} | ||
} | ||
|
||
private fun extractToken(request: HttpServletRequest): String? { | ||
val bearerToken = request.getHeader(JwtTokenInfo.AUTHORIZATION_HEADER) | ||
return if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(JwtTokenInfo.BEARER_TYPE)) { | ||
bearerToken.substring(JwtTokenInfo.BEARER_TYPE.length).trim() | ||
} else null | ||
} | ||
} |
Oops, something went wrong.