-
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: OAuth + jwt 인증 구현 및 s3 multiUpload 구현
- Loading branch information
Showing
23 changed files
with
637 additions
and
21 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
32 changes: 32 additions & 0 deletions
32
src/main/java/com/hackathon/TimeLapse/config/CorsConfig.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,32 @@ | ||
package com.hackathon.TimeLapse.config; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import org.springframework.web.cors.CorsConfiguration; | ||
import org.springframework.web.cors.CorsConfigurationSource; | ||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
|
||
public class CorsConfig implements WebMvcConfigurer { | ||
|
||
public static CorsConfigurationSource apiConfigurationSource() { | ||
|
||
CorsConfiguration configuration = new CorsConfiguration(); | ||
|
||
ArrayList<String> allowedOriginPatterns = new ArrayList<>(); | ||
allowedOriginPatterns.add("http://localhost:8080"); | ||
allowedOriginPatterns.add("http://localhost:3000"); | ||
// allowedOriginPatterns.add("{프론트 배포 URL}"); | ||
|
||
ArrayList<String> allowedHttpMethods = new ArrayList<>(List.of("GET", "POST")); | ||
|
||
configuration.setAllowedOrigins(allowedOriginPatterns); | ||
configuration.setAllowedMethods(allowedHttpMethods); | ||
|
||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||
source.registerCorsConfiguration("/**", configuration); | ||
|
||
return source; | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
src/main/java/com/hackathon/TimeLapse/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,63 @@ | ||
package com.hackathon.TimeLapse.config; | ||
|
||
import java.util.Arrays; | ||
import java.util.stream.Stream; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; | ||
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.configurers.AbstractHttpConfigurer; | ||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
import com.hackathon.TimeLapse.oauth.JwtAuthenticationFilter; | ||
import com.hackathon.TimeLapse.oauth.JwtTokenProvider; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
@RequiredArgsConstructor | ||
public class SecurityConfig { | ||
|
||
private final JwtTokenProvider jwtTokenProvider; | ||
|
||
private final String[] swaggerUrls = {"/","/swagger-ui/**", "/v3/api-docs/**"}; | ||
private final String[] authUrls = {"/kakao/callback/**", "/api/auth/kakao", "/api/files/**"}; | ||
private final String[] allowedUrls = Stream.concat(Arrays.stream(swaggerUrls), Arrays.stream(authUrls)) | ||
.toArray(String[]::new); | ||
|
||
@Bean | ||
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { | ||
return configuration.getAuthenticationManager(); | ||
} | ||
|
||
@Bean | ||
public BCryptPasswordEncoder bCryptPasswordEncoder() { | ||
return new BCryptPasswordEncoder(); | ||
} | ||
|
||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
|
||
http | ||
.cors((cors) -> cors | ||
.configurationSource(CorsConfig.apiConfigurationSource())) | ||
.csrf(AbstractHttpConfigurer::disable) | ||
.formLogin(AbstractHttpConfigurer::disable) | ||
.httpBasic(AbstractHttpConfigurer::disable) | ||
.authorizeHttpRequests((auth) -> auth | ||
.requestMatchers(allowedUrls).permitAll() | ||
.requestMatchers("/test").permitAll() | ||
.anyRequest().authenticated() | ||
); | ||
|
||
http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class); | ||
|
||
return http.build(); | ||
} | ||
} |
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,33 +1,54 @@ | ||
package com.hackathon.TimeLapse.domain; | ||
|
||
import com.hackathon.TimeLapse.domain.common.BaseEntity; | ||
import jakarta.persistence.*; | ||
import lombok.*; | ||
import org.hibernate.annotations.DynamicInsert; | ||
import org.hibernate.annotations.DynamicUpdate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
@Entity | ||
@Getter | ||
@DynamicUpdate | ||
@DynamicInsert | ||
@Builder | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
import com.hackathon.TimeLapse.domain.common.BaseEntity; | ||
import com.hackathon.TimeLapse.oauth.OAuthProvider; | ||
|
||
import jakarta.persistence.CascadeType; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.EnumType; | ||
import jakarta.persistence.Enumerated; | ||
import jakarta.persistence.FetchType; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.OneToMany; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Getter | ||
@Entity | ||
public class Member extends BaseEntity { | ||
@Id | ||
@GeneratedValue( | ||
strategy = GenerationType.IDENTITY | ||
strategy = GenerationType.IDENTITY | ||
) | ||
private Long id; | ||
|
||
private String email; | ||
|
||
private String nickname; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private OAuthProvider oAuthProvider; | ||
|
||
@OneToMany( | ||
mappedBy = "member", | ||
cascade = {CascadeType.ALL} | ||
mappedBy = "member", | ||
cascade = {CascadeType.ALL}, | ||
fetch = FetchType.EAGER | ||
) | ||
@Builder.Default | ||
private List<Article> articleList = new ArrayList<>(); | ||
|
||
@Builder | ||
public Member(String email, String nickname, OAuthProvider oAuthProvider) { | ||
this.email = email; | ||
this.nickname = nickname; | ||
this.oAuthProvider = oAuthProvider; | ||
} | ||
} |
6 changes: 5 additions & 1 deletion
6
src/main/java/com/hackathon/TimeLapse/member/MemberRepository.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,7 +1,11 @@ | ||
package com.hackathon.TimeLapse.member; | ||
|
||
import com.hackathon.TimeLapse.domain.Member; | ||
import java.util.Optional; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import com.hackathon.TimeLapse.domain.Member; | ||
|
||
public interface MemberRepository extends JpaRepository<Member, Long> { | ||
Optional<Member> findByEmail(String email); | ||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/com/hackathon/TimeLapse/oauth/AuthController.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.hackathon.TimeLapse.oauth; | ||
|
||
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; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/auth") | ||
public class AuthController { | ||
private final OAuthLoginService oAuthLoginService; | ||
|
||
@PostMapping("/kakao") | ||
public ResponseEntity<AuthTokens> loginKakao(@RequestBody KakaoLoginParams params) { | ||
return ResponseEntity.ok(oAuthLoginService.login(params)); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/com/hackathon/TimeLapse/oauth/AuthTokens.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.hackathon.TimeLapse.oauth; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class AuthTokens { | ||
private String accessToken; | ||
private String refreshToken; | ||
private String grantType; | ||
private Long expiresIn; | ||
|
||
public static AuthTokens of(String accessToken, String refreshToken, String grantType, Long expiresIn) { | ||
return new AuthTokens(accessToken, refreshToken, grantType, expiresIn); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/main/java/com/hackathon/TimeLapse/oauth/AuthTokensGenerator.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,33 @@ | ||
package com.hackathon.TimeLapse.oauth; | ||
|
||
import java.util.Date; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class AuthTokensGenerator { | ||
private static final String BEARER_TYPE = "Bearer"; | ||
private static final long ACCESS_TOKEN_EXPIRE_TIME = 1000 * 60 * 30; // 30분 | ||
private static final long REFRESH_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 24 * 7; // 7일 | ||
|
||
private final JwtTokenProvider jwtTokenProvider; | ||
|
||
public AuthTokens generate(Long memberId) { | ||
long now = (new Date()).getTime(); | ||
Date accessTokenExpiredAt = new Date(now + ACCESS_TOKEN_EXPIRE_TIME); | ||
Date refreshTokenExpiredAt = new Date(now + REFRESH_TOKEN_EXPIRE_TIME); | ||
|
||
String subject = memberId.toString(); | ||
String accessToken = jwtTokenProvider.generate(subject, accessTokenExpiredAt); | ||
String refreshToken = jwtTokenProvider.generate(subject, refreshTokenExpiredAt); | ||
|
||
return AuthTokens.of(accessToken, refreshToken, BEARER_TYPE, ACCESS_TOKEN_EXPIRE_TIME / 1000L); | ||
} | ||
|
||
public Long extractMemberId(String accessToken) { | ||
return Long.valueOf(jwtTokenProvider.extractSubject(accessToken)); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/hackathon/TimeLapse/oauth/ClientConfig.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,14 @@ | ||
package com.hackathon.TimeLapse.oauth; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
@Configuration | ||
public class ClientConfig { | ||
|
||
@Bean | ||
public RestTemplate restTemplate() { | ||
return new RestTemplate(); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/com/hackathon/TimeLapse/oauth/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,54 @@ | ||
package com.hackathon.TimeLapse.oauth; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.GrantedAuthority; | ||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.AllArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@AllArgsConstructor | ||
@Slf4j | ||
@Component | ||
public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||
|
||
private final JwtTokenProvider jwtTokenProvider; | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) | ||
throws IOException, ServletException { | ||
log.info("[*] Jwt Filter"); | ||
String token = resolveToken(request); | ||
log.info("[*] Jwt token >>>>> " + token); | ||
if (token != null) { | ||
Authentication authentication = getAuthentication(token); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); //SecurityContextHolder에 담기 | ||
} | ||
chain.doFilter(request, response); | ||
} | ||
private Authentication getAuthentication(String token) { | ||
log.info("[*] subject: "+jwtTokenProvider.extractSubject(token)); | ||
return new UsernamePasswordAuthenticationToken(jwtTokenProvider.extractSubject(token), null, | ||
Collections.singleton(new SimpleGrantedAuthority("ROLE_MEMBER"))); | ||
} | ||
private String resolveToken(HttpServletRequest request) { | ||
String bearerToken = request.getHeader("Authorization"); | ||
if (bearerToken != null && bearerToken.startsWith("Bearer ")) { | ||
return bearerToken.split(" ")[1]; | ||
} | ||
return null; | ||
} | ||
} |
Oops, something went wrong.