-
Notifications
You must be signed in to change notification settings - Fork 0
feat : login 추가 #3
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
Changes from all commits
3d856c0
4421d59
988aac5
643b841
6ca0104
7fda6cf
f0a2078
33e53b0
697da14
2e5bdb8
806e642
109d4aa
6dee27e
d926cdc
7b1198b
20624e4
699bffc
b799b96
3f6e218
3b2964d
ac9a3d4
3cf5c26
924478d
f0f6344
3240c69
f5d3f45
602bc62
14839bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ out/ | |
|
|
||
|
|
||
| application.properties | ||
| application.yml | ||
|
|
||
| src/main/resources/application.properties | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package backend.greatjourney.config; | ||
|
|
||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| import com.querydsl.jpa.impl.JPAQueryFactory; | ||
|
|
||
| import jakarta.persistence.EntityManager; | ||
| import jakarta.persistence.PersistenceContext; | ||
|
|
||
| @Configuration | ||
| public class QueryDslConfig { | ||
|
|
||
| @PersistenceContext | ||
| private EntityManager entityManager; | ||
|
|
||
| @Bean | ||
| public JPAQueryFactory jpaQueryFactory() { | ||
| return new JPAQueryFactory(entityManager); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,40 @@ | ||
| package backend.greatjourney.config; | ||
|
|
||
| import io.swagger.v3.oas.annotations.security.SecurityRequirement; | ||
| import io.swagger.v3.oas.annotations.security.SecurityScheme; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| import io.swagger.v3.oas.models.Components; | ||
| import io.swagger.v3.oas.models.OpenAPI; | ||
| import org.springframework.context.annotation.Bean; | ||
| import io.swagger.v3.oas.models.info.Info; | ||
| import io.swagger.v3.oas.models.security.SecurityRequirement; | ||
| import io.swagger.v3.oas.models.security.SecurityScheme; | ||
|
|
||
| @Configuration | ||
| public class SwaggerConfig { | ||
| // @Bean | ||
| // public OpenAPI api() { | ||
| // SecurityScheme apiKey = new SecurityScheme() | ||
| // .type(SecurityScheme.Type.APIKEY) | ||
| // .in(SecurityScheme.In.HEADER) | ||
| // .name("Authorization"); | ||
| // | ||
| // SecurityRequirement securityRequirement = new SecurityRequirement() | ||
| // .addList("Bearer Token"); | ||
| // | ||
| // return new OpenAPI() | ||
| // .components(new Components().addSecuritySchemes("Bearer Token", apiKey)) | ||
| // .addSecurityItem(securityRequirement); | ||
| // } | ||
| } | ||
| @Bean | ||
| public OpenAPI openAPI() { | ||
| SecurityRequirement securityRequirement = new SecurityRequirement().addList("BearerAuth"); | ||
|
|
||
| return new OpenAPI() | ||
| .components(new Components()) | ||
| .info(apiInfo()) | ||
| .addSecurityItem(securityRequirement) | ||
| .schemaRequirement("BearerAuth", securityScheme()); | ||
| } | ||
|
Comment on lines
+14
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the security scheme registration method. The method Apply this diff to fix the security scheme registration: return new OpenAPI()
- .components(new Components())
+ .components(new Components().addSecuritySchemes("BearerAuth", securityScheme()))
.info(apiInfo())
.addSecurityItem(securityRequirement)
- .schemaRequirement("BearerAuth", securityScheme());
🤖 Prompt for AI Agents |
||
|
|
||
| private Info apiInfo() { | ||
| return new Info() | ||
| .title("어디로 API") | ||
| .description("대장정이팀 API 명세서입니다") | ||
| .version("1.0.0"); | ||
| } | ||
|
|
||
| private SecurityScheme securityScheme() { | ||
| return new SecurityScheme() | ||
| .type(SecurityScheme.Type.HTTP) | ||
| .scheme("bearer") | ||
| .bearerFormat("JWT") | ||
| .in(SecurityScheme.In.HEADER) | ||
| .name("Authorization"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package backend.greatjourney.domain.token.dto; | ||
|
|
||
| import lombok.AllArgsConstructor; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @AllArgsConstructor | ||
| public class TokenResponse { | ||
| private String accessToken; | ||
| private String refreshToken; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,31 @@ | ||||||||||
| package backend.greatjourney.domain.token.entity; | ||||||||||
|
|
||||||||||
| import java.time.Instant; | ||||||||||
|
|
||||||||||
| import org.springframework.web.bind.annotation.RequestParam; | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused import. The Apply this diff to remove the unused import: import java.time.Instant;
-import org.springframework.web.bind.annotation.RequestParam;
-
import jakarta.persistence.Entity;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| import jakarta.persistence.Entity; | ||||||||||
| import jakarta.persistence.Id; | ||||||||||
| import lombok.Builder; | ||||||||||
| import lombok.Getter; | ||||||||||
| import lombok.NoArgsConstructor; | ||||||||||
|
|
||||||||||
| @Entity | ||||||||||
| @NoArgsConstructor | ||||||||||
| @Getter | ||||||||||
| public class RefreshToken { | ||||||||||
|
|
||||||||||
| @Id | ||||||||||
| private String tokenId; | ||||||||||
| private Long userId; | ||||||||||
| private String token; | ||||||||||
| private Instant expiryDate; | ||||||||||
|
Comment on lines
+18
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding JPA column annotations for better control. Consider adding column annotations for better database schema control and validation: @Id
+ @Column(length = 255, nullable = false)
private String tokenId;
+
+ @Column(nullable = false)
private Long userId;
+
+ @Column(columnDefinition = "TEXT", nullable = false)
private String token;
+
+ @Column(nullable = false)
private Instant expiryDate;The 🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| @Builder | ||||||||||
| private RefreshToken(Long userId, String id, String token, Instant expiryDate) { | ||||||||||
| this.userId = userId; | ||||||||||
| this.tokenId = id; | ||||||||||
| this.token = token; | ||||||||||
| this.expiryDate = expiryDate; | ||||||||||
| } | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,11 @@ | ||||||||||
| package backend.greatjourney.domain.token.repository; | ||||||||||
|
|
||||||||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||||||||
|
|
||||||||||
| import backend.greatjourney.domain.token.entity.RefreshToken; | ||||||||||
|
|
||||||||||
| public interface RefreshTokenRepository extends JpaRepository<RefreshToken,Long> { | ||||||||||
|
|
||||||||||
| Void deleteByToken(String token); | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the return type for delete operation. The - Void deleteByToken(String token);
+ void deleteByToken(String token);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| RefreshToken findByUserId(Long userId); | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use Optional for null safety. The - RefreshToken findByUserId(Long userId);
+ Optional<RefreshToken> findByUserId(Long userId);🤖 Prompt for AI Agents |
||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,43 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package backend.greatjourney.domain.token.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import jakarta.servlet.FilterChain; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import jakarta.servlet.ServletException; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import jakarta.servlet.http.HttpServletRequest; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import jakarta.servlet.http.HttpServletResponse; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.http.HttpHeaders; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.web.filter.OncePerRequestFilter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.io.IOException; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final JwtTokenProvider jwtTokenProvider; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.jwtTokenProvider = jwtTokenProvider; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protected void doFilterInternal(HttpServletRequest request, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HttpServletResponse response, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FilterChain filterChain) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throws ServletException, IOException { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (authHeader != null && authHeader.startsWith("Bearer ")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String token = authHeader.substring("Bearer ".length()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (jwtTokenProvider.validateToken(token)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UsernamePasswordAuthenticationToken authentication = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (UsernamePasswordAuthenticationToken) jwtTokenProvider.getAuthentication(token); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SecurityContextHolder.getContext().setAuthentication(authentication); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filterChain.doFilter(request, response); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+22
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add exception handling and improve token validation robustness. The current implementation has several areas for improvement:
Consider this improved implementation: @Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring("Bearer ".length());
+ try {
if (jwtTokenProvider.validateToken(token)) {
- UsernamePasswordAuthenticationToken authentication =
- (UsernamePasswordAuthenticationToken) jwtTokenProvider.getAuthentication(token);
+ Authentication authentication = jwtTokenProvider.getAuthentication(token);
+ if (authentication instanceof UsernamePasswordAuthenticationToken) {
SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
}
+ } catch (Exception e) {
+ // Log the exception but continue the filter chain
+ // Invalid tokens should not break the request processing
+ }
}
filterChain.doFilter(request, response);
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||
| package backend.greatjourney.domain.token.service; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.authentication.AuthenticationManager; | ||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.core.Authentication; | ||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Component; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Component | ||||||||||||||||||||||||||||||||||||||
| public class JwtAuthenticationManager implements AuthenticationManager { | ||||||||||||||||||||||||||||||||||||||
| private final JwtTokenProvider jwtTokenProvider; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| public JwtAuthenticationManager(JwtTokenProvider jwtTokenProvider) { | ||||||||||||||||||||||||||||||||||||||
| this.jwtTokenProvider = jwtTokenProvider; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||
| public Authentication authenticate(Authentication authentication) { | ||||||||||||||||||||||||||||||||||||||
| String token = authentication.getCredentials().toString(); | ||||||||||||||||||||||||||||||||||||||
| return jwtTokenProvider.getAuthentication(token); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+16
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation and error handling. The current implementation lacks proper validation and error handling, which could lead to runtime exceptions. Consider this improved implementation: @Override
public Authentication authenticate(Authentication authentication) {
+ if (authentication == null || authentication.getCredentials() == null) {
+ throw new AuthenticationException("Invalid authentication object") {};
+ }
+
String token = authentication.getCredentials().toString();
+ if (token == null || token.trim().isEmpty()) {
+ throw new AuthenticationException("Invalid token") {};
+ }
+
return jwtTokenProvider.getAuthentication(token);
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate OAuth2 client dependency.
The
spring-boot-starter-oauth2-clientdependency is declared twice (lines 38 and 47). This can cause confusion and potential version conflicts.Apply this diff to remove the duplicate:
//jwt implementation 'io.jsonwebtoken:jjwt-api:0.12.3' implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.3' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' // AWS SDK for S3 (v1)Also applies to: 47-47
🤖 Prompt for AI Agents