Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions src/main/java/backend/receipt/global/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,55 @@
package backend.receipt.global.config;

import backend.receipt.member.security.JwtAuthenticationFilter;
import backend.receipt.member.service.JwtTokenProvider;
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.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@RequiredArgsConstructor
public class SecurityConfig {

private final JwtTokenProvider jwtTokenProvider;

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter(jwtTokenProvider);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(
"/swagger-ui/**",
"/v3/api-docs/**",
"/swagger-resources/**"
"/swagger-resources/**",
"/auth/login",
"/stores/**",
"/member/**",
"/reviews/**"
).permitAll()
.anyRequest().permitAll()
);
.requestMatchers(
"/reviews",
"/auth/logout",
"/love/**",
"/points/**",
"reward/**",
"/total",
"history",
"/receipts/**"
).authenticated()
.anyRequest().denyAll()
)
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);

return http.build();
}
}
}
14 changes: 13 additions & 1 deletion src/main/java/backend/receipt/global/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package backend.receipt.global.config;


import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

Expand All @@ -12,7 +15,15 @@ public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.components(new Components())
.components(new Components()
.addSecuritySchemes("BearerAuth",
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
))
.addSecurityItem(new SecurityRequirement()
.addList("BearerAuth"))
.info(apiInfo());
}

Expand All @@ -22,4 +33,5 @@ private Info apiInfo() {
.description("Receipt API 문서")
.version("v1");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package backend.receipt.member.security;

import backend.receipt.member.service.JwtTokenProvider;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final JwtTokenProvider jwtTokenProvider;

@Autowired
public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {

String header = request.getHeader("Authorization");

if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
try {
if (jwtTokenProvider.validateToken(token)) {
Authentication authentication = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (JwtException e) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
}

filterChain.doFilter(request, response);
}
}
17 changes: 17 additions & 0 deletions src/main/java/backend/receipt/member/service/JwtTokenProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Collections;
import java.util.Date;

@Component
Expand Down Expand Up @@ -47,5 +50,19 @@ public boolean validateToken(String token) {
throw new JwtException("유효하지 않은 JWT 토큰입니다.");
}
}
public Authentication getAuthentication(String token) {
Claims claims = getClaims(token);
String email = claims.getSubject();
return new UsernamePasswordAuthenticationToken(email, "", Collections.emptyList());
}

private Claims getClaims(String token) {
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
}

}

27 changes: 25 additions & 2 deletions src/main/java/backend/receipt/store/service/StoreService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import backend.receipt.store.dto.response.KakaoPlaceDetail;
import backend.receipt.store.dto.response.StoreResponse;
import backend.receipt.store.repository.StoreRepository;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.json.JSONArray;
import org.json.JSONObject;
Expand Down Expand Up @@ -113,8 +114,30 @@ public StoreResponse getStoreDetail(Long storeId) {
return response;
}



//초기데이터
@PostConstruct
public void initStoresOnStartup() {
try {
StoreRequest store1 = new StoreRequest();
store1.setQuery("베이커리");
store1.setName("파리바게뜨 시흥장현점");
searchAndSaveStoreByName(store1);

StoreRequest store2 = new StoreRequest();
store2.setQuery("카페");
store2.setName("일리카페 시흥시청점");
searchAndSaveStoreByName(store2);

StoreRequest store3 = new StoreRequest();
store3.setQuery("편의점");
store3.setName("CU 시흥시청점");
searchAndSaveStoreByName(store3);

System.out.println("[초기 가맹점 등록 완료]");
} catch (Exception e) {
System.err.println("[초기 가맹점 등록 실패] " + e.getMessage());
}
}
// kakao api 관련
// kakao api 호출
private String fetchKakaoApiResponse(String query, double x, double y, int radius) {
Expand Down