From cb2df270325a9ead26fa2171d25d7eefe7d8e250 Mon Sep 17 00:00:00 2001 From: downfa11 Date: Tue, 10 Dec 2024 15:17:41 +0900 Subject: [PATCH] =?UTF-8?q?#1=20feat:=20=EC=86=8C=EC=85=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=EA=B3=BC=20Spring=20Security6=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 + .../ns/solve/Auth/kakao/KakaoController.java | 56 +++++++++ .../com/ns/solve/Auth/kakao/KakaoDTO.java | 14 +++ .../com/ns/solve/Auth/kakao/KakaoService.java | 116 ++++++++++++++++++ .../ns/solve/Auth/naver/NaverController.java | 26 ++++ .../com/ns/solve/Auth/naver/NaverDTO.java | 13 ++ .../com/ns/solve/Auth/naver/NaverService.java | 107 ++++++++++++++++ .../com/ns/solve/Config/QuerydslConfig.java | 19 +++ .../com/ns/solve/Config/SecurityConfig.java | 98 +++++++++++++++ .../java/com/ns/solve/Domain/Membership.java | 17 ++- .../com/ns/solve/Domain/dto/KakaoProfile.java | 42 +++++++ .../com/ns/solve/Domain/dto/KakaoRequest.java | 7 ++ .../com/ns/solve/Domain/dto/KakaoToken.java | 13 ++ .../ns/solve/Domain/dto/MessageEntity.java | 14 +++ .../MembershipCustomRepository.java | 1 + .../MembershipCustomRepositoryImpl.java | 5 + .../ns/solve/Service/MembershipService.java | 4 + .../java/com/ns/solve/Utils/JwtToken.java | 27 ++++ .../com/ns/solve/Utils/JwtTokenProvider.java | 4 + 19 files changed, 576 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/ns/solve/Auth/kakao/KakaoController.java create mode 100644 src/main/java/com/ns/solve/Auth/kakao/KakaoDTO.java create mode 100644 src/main/java/com/ns/solve/Auth/kakao/KakaoService.java create mode 100644 src/main/java/com/ns/solve/Auth/naver/NaverController.java create mode 100644 src/main/java/com/ns/solve/Auth/naver/NaverDTO.java create mode 100644 src/main/java/com/ns/solve/Auth/naver/NaverService.java create mode 100644 src/main/java/com/ns/solve/Config/QuerydslConfig.java create mode 100644 src/main/java/com/ns/solve/Config/SecurityConfig.java create mode 100644 src/main/java/com/ns/solve/Domain/dto/KakaoProfile.java create mode 100644 src/main/java/com/ns/solve/Domain/dto/KakaoRequest.java create mode 100644 src/main/java/com/ns/solve/Domain/dto/KakaoToken.java create mode 100644 src/main/java/com/ns/solve/Domain/dto/MessageEntity.java create mode 100644 src/main/java/com/ns/solve/Utils/JwtToken.java create mode 100644 src/main/java/com/ns/solve/Utils/JwtTokenProvider.java diff --git a/build.gradle b/build.gradle index 5d8c1ac..067aa93 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' + //json + implementation 'com.googlecode.json-simple:json-simple:1.1.1' + //Swagger implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' diff --git a/src/main/java/com/ns/solve/Auth/kakao/KakaoController.java b/src/main/java/com/ns/solve/Auth/kakao/KakaoController.java new file mode 100644 index 0000000..09d9ef3 --- /dev/null +++ b/src/main/java/com/ns/solve/Auth/kakao/KakaoController.java @@ -0,0 +1,56 @@ +package com.ns.solve.Auth.kakao; + +import com.ns.solve.Auth.naver.NaverService; +import com.ns.solve.Domain.dto.MessageEntity; +import com.ns.solve.Service.MembershipService; +import com.ns.solve.Utils.JwtToken; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.view.RedirectView; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("kakao") +public class KakaoController { + + private final KakaoService kakaoService; + private final NaverService naverService; + private final MembershipService membershipService; + + @RequestMapping(value="/", method= RequestMethod.GET) + public String login(Model model) { + model.addAttribute("kakaoUrl", kakaoService.getKakaoLogin()); + model.addAttribute("naverUrl", naverService.getNaverLogin()); + return "index"; + } + + @GetMapping("/login") + public RedirectView login(){ + return new RedirectView(kakaoService.getKakaoLogin()); + } + + @GetMapping("/callback") + public ResponseEntity callback(HttpServletRequest request) throws Exception { + KakaoDTO kakaoInfo = kakaoService.getKakaoInfo(request.getParameter("code")); + + Long id = kakaoInfo.getId(); + JwtToken token = membershipService.LoginMembership(id); + + if (token!=null) + return ResponseEntity.ok() + .body(new MessageEntity("Success ", token)); + else return ResponseEntity.ok() + .body(new MessageEntity("Fail ","token is empty.")); // empty시 register시켜야함. + } + + + +} diff --git a/src/main/java/com/ns/solve/Auth/kakao/KakaoDTO.java b/src/main/java/com/ns/solve/Auth/kakao/KakaoDTO.java new file mode 100644 index 0000000..537c209 --- /dev/null +++ b/src/main/java/com/ns/solve/Auth/kakao/KakaoDTO.java @@ -0,0 +1,14 @@ +package com.ns.solve.Auth.kakao; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class KakaoDTO { + + private long id; + private String email; + private String nickname; + +} \ No newline at end of file diff --git a/src/main/java/com/ns/solve/Auth/kakao/KakaoService.java b/src/main/java/com/ns/solve/Auth/kakao/KakaoService.java new file mode 100644 index 0000000..77e1fa0 --- /dev/null +++ b/src/main/java/com/ns/solve/Auth/kakao/KakaoService.java @@ -0,0 +1,116 @@ +package com.ns.solve.Auth.kakao; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + + +@Service +@Slf4j +@RequiredArgsConstructor +public class KakaoService { + + @Value("${KAKAO_CLIENT_ID}") + private String KAKAO_CLIENT_ID; + + @Value("${KAKAO_CLIENT_SECRET}") + private String KAKAO_CLIENT_SECRET; + + @Value("${KAKAO_REDIRECT_URL}") + private String KAKAO_REDIRECT_URL; + + private final static String KAKAO_AUTH_URI = "https://kauth.kakao.com"; + private final static String KAKAO_API_URI = "https://kapi.kakao.com"; + + public String getKakaoLogin() { + return KAKAO_AUTH_URI + "/oauth/authorize" + + "?client_id=" + KAKAO_CLIENT_ID + + "&redirect_uri=" + KAKAO_REDIRECT_URL + + "&response_type=code"; + } + + public KakaoDTO getKakaoInfo(String code) throws Exception { + if (code == null) throw new Exception("Failed get authorization code"); + + String accessToken = ""; + String refreshToken = ""; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-type", "application/x-www-form-urlencoded"); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("grant_type" , "authorization_code"); + params.add("client_id" , KAKAO_CLIENT_ID); + params.add("client_secret", KAKAO_CLIENT_SECRET); + params.add("code" , code); + params.add("redirect_uri" , KAKAO_REDIRECT_URL); + + RestTemplate restTemplate = new RestTemplate(); + HttpEntity> httpEntity = new HttpEntity<>(params, headers); + + ResponseEntity response = restTemplate.exchange( + KAKAO_AUTH_URI + "/oauth/token", + HttpMethod.POST, + httpEntity, + String.class + ); + + JSONParser jsonParser = new JSONParser(); + JSONObject jsonObj = (JSONObject) jsonParser.parse(response.getBody()); + + accessToken = (String) jsonObj.get("access_token"); + refreshToken = (String) jsonObj.get("refresh_token"); + } catch (Exception e) { + throw new Exception("API call failed"); + } + + return getUserInfoWithToken(accessToken); + } + + private KakaoDTO getUserInfoWithToken(String accessToken) throws Exception { + //HttpHeader 생성 + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Bearer " + accessToken); + headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); + + //HttpHeader 담기 + RestTemplate rt = new RestTemplate(); + HttpEntity> httpEntity = new HttpEntity<>(headers); + ResponseEntity response = rt.exchange( + KAKAO_API_URI + "/v2/user/me", + HttpMethod.POST, + httpEntity, + String.class + ); + + log.info("Received json : "+ response.getBody()); + //Response 데이터 파싱 + JSONParser jsonParser = new JSONParser(); + JSONObject jsonObj = (JSONObject) jsonParser.parse(response.getBody()); + JSONObject account = (JSONObject) jsonObj.get("kakao_account"); + JSONObject profile = (JSONObject) account.get("profile"); + + long id = (long) jsonObj.get("id"); + String email = String.valueOf(account.get("email")); + String nickname = String.valueOf(profile.get("nickname")); + + return KakaoDTO.builder() + .id(id) + .email(email) + .nickname(nickname).build(); + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/ns/solve/Auth/naver/NaverController.java b/src/main/java/com/ns/solve/Auth/naver/NaverController.java new file mode 100644 index 0000000..43196a1 --- /dev/null +++ b/src/main/java/com/ns/solve/Auth/naver/NaverController.java @@ -0,0 +1,26 @@ +package com.ns.solve.Auth.naver; + +import com.ns.solve.Domain.dto.MessageEntity; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("naver") +public class NaverController { + + private final NaverService naverService; + + @GetMapping("/callback") + public ResponseEntity callback(HttpServletRequest request) throws Exception { + NaverDTO naverInfo = naverService.getNaverInfo(request.getParameter("code")); + + return ResponseEntity.ok() + .body(new MessageEntity("Success", naverInfo)); + } + +} \ No newline at end of file diff --git a/src/main/java/com/ns/solve/Auth/naver/NaverDTO.java b/src/main/java/com/ns/solve/Auth/naver/NaverDTO.java new file mode 100644 index 0000000..a2e285b --- /dev/null +++ b/src/main/java/com/ns/solve/Auth/naver/NaverDTO.java @@ -0,0 +1,13 @@ +package com.ns.solve.Auth.naver; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class NaverDTO { + + private String id; + private String email; + private String name; + +} diff --git a/src/main/java/com/ns/solve/Auth/naver/NaverService.java b/src/main/java/com/ns/solve/Auth/naver/NaverService.java new file mode 100644 index 0000000..75b4c28 --- /dev/null +++ b/src/main/java/com/ns/solve/Auth/naver/NaverService.java @@ -0,0 +1,107 @@ +package com.ns.solve.Auth.naver; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +@Service +public class NaverService { + + @Value("${NAVER_CLIENT_ID}") + private String NAVER_CLIENT_ID; + + @Value("${NAVER_CLIENT_SECRET}") + private String NAVER_CLIENT_SECRET; + + @Value("${NAVER_REDIRECT_URL}") + private String NAVER_REDIRECT_URL; + + private final static String NAVER_AUTH_URI = "https://nid.naver.com"; + private final static String NAVER_API_URI = "https://openapi.naver.com"; + + public String getNaverLogin() { + return NAVER_AUTH_URI + "/oauth2.0/authorize" + + "?client_id=" + NAVER_CLIENT_ID + + "&redirect_uri=" + NAVER_REDIRECT_URL + + "&response_type=code"; + } + + public NaverDTO getNaverInfo(String code) throws Exception { + if (code == null) throw new Exception("Failed get authorization code"); + + String accessToken = ""; + String refreshToken = ""; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-type", "application/x-www-form-urlencoded"); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("grant_type" , "authorization_code"); + params.add("client_id" , NAVER_CLIENT_ID); + params.add("client_secret", NAVER_CLIENT_SECRET); + params.add("code" , code); + params.add("redirect_uri" , NAVER_REDIRECT_URL); + + RestTemplate restTemplate = new RestTemplate(); + HttpEntity> httpEntity = new HttpEntity<>(params, headers); + + ResponseEntity response = restTemplate.exchange( + NAVER_AUTH_URI + "/oauth2.0/token", + HttpMethod.POST, + httpEntity, + String.class + ); + + JSONParser jsonParser = new JSONParser(); + JSONObject jsonObj = (JSONObject) jsonParser.parse(response.getBody()); + + accessToken = (String) jsonObj.get("access_token"); + refreshToken = (String) jsonObj.get("refresh_token"); + } catch (Exception e) { + throw new Exception("API call failed"); + } + + return getUserInfoWithToken(accessToken); + } + + private NaverDTO getUserInfoWithToken(String accessToken) throws Exception { + //HttpHeader 생성 + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Bearer " + accessToken); + headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); + + //HttpHeader 담기 + RestTemplate rt = new RestTemplate(); + HttpEntity> httpEntity = new HttpEntity<>(headers); + ResponseEntity response = rt.exchange( + NAVER_API_URI + "/v1/nid/me", + HttpMethod.POST, + httpEntity, + String.class + ); + + //Response 데이터 파싱 + JSONParser jsonParser = new JSONParser(); + JSONObject jsonObj = (JSONObject) jsonParser.parse(response.getBody()); + JSONObject account = (JSONObject) jsonObj.get("response"); + + String id = String.valueOf(account.get("id")); + String email = String.valueOf(account.get("email")); + String name = String.valueOf(account.get("name")); + + return NaverDTO.builder() + .id(id) + .email(email) + .name(name).build(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/ns/solve/Config/QuerydslConfig.java b/src/main/java/com/ns/solve/Config/QuerydslConfig.java new file mode 100644 index 0000000..01aa2cb --- /dev/null +++ b/src/main/java/com/ns/solve/Config/QuerydslConfig.java @@ -0,0 +1,19 @@ +package com.ns.solve.Config; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class QuerydslConfig { + + @PersistenceContext + private EntityManager entityManager; + + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(entityManager); + } +} diff --git a/src/main/java/com/ns/solve/Config/SecurityConfig.java b/src/main/java/com/ns/solve/Config/SecurityConfig.java new file mode 100644 index 0000000..1fc3de5 --- /dev/null +++ b/src/main/java/com/ns/solve/Config/SecurityConfig.java @@ -0,0 +1,98 @@ +package com.ns.solve.Config; + +import com.ns.solve.Repository.MembershipRepository; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebFluxSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + return http.authorizeHttpRequests(auth -> auth + .requestMatchers("/login").permitAll() + .requestMatchers("/admin/**").hasRole("ADMIN") + .requestMatchers("/problem/**").hasRole("MANAGER") + .requestMatchers("/**").hasRole("USER") + .anyRequest().authenticated() + ) + .formLogin(form -> form + .loginPage("/login") + .defaultSuccessUrl("/", true) + .permitAll() + ) + .logout(logout -> logout + .logoutUrl("/logout") + .logoutSuccessUrl("/login?logout") + .permitAll() + ) + .csrf(csrf -> csrf.disable()) + .build(); + } + + + @Bean + public UserDetailsService inMemoryUserDetailsService() { + UserDetails user = User.withUsername("user") + .password(passwordEncoder().encode("password")) + .roles("USER") + .build(); + + UserDetails admin = User.withUsername("admin") + .password(passwordEncoder().encode("admin")) + .roles("ADMIN") + .build(); + + return new InMemoryUserDetailsManager(user, admin); + } + + @Bean + public UserDetailsService dbUserDetailsService(MembershipRepository membershipRepository) { + return account -> membershipRepository.findByAccount(account) + .map(member -> User.withUsername(member.getName()) + .password(member.getPassword()) + .roles(member.getRoleName()) + .build() + ).orElseThrow(() -> new UsernameNotFoundException("Account not found: " + account)); + } + + @Bean + public AuthenticationManager authenticationManager(UserDetailsService inMemoryUserDetailsService, UserDetailsService dbUserDetailsService, PasswordEncoder passwordEncoder) { + // 다중 인증 처리를 위한 AuthenticationManager + + DaoAuthenticationProvider inMemoryAuthProvider = new DaoAuthenticationProvider(); + inMemoryAuthProvider.setUserDetailsService(inMemoryUserDetailsService); + inMemoryAuthProvider.setPasswordEncoder(passwordEncoder); + + DaoAuthenticationProvider dbAuthProvider = new DaoAuthenticationProvider(); + dbAuthProvider.setUserDetailsService(dbUserDetailsService); + dbAuthProvider.setPasswordEncoder(passwordEncoder); + + ProviderManager authManager = new ProviderManager(inMemoryAuthProvider, dbAuthProvider); + return authManager; + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + +} + + + + diff --git a/src/main/java/com/ns/solve/Domain/Membership.java b/src/main/java/com/ns/solve/Domain/Membership.java index 1dc42f2..d6901e2 100644 --- a/src/main/java/com/ns/solve/Domain/Membership.java +++ b/src/main/java/com/ns/solve/Domain/Membership.java @@ -29,25 +29,22 @@ public class Membership { private String nickname; private String address; private String email; + private String password; public enum ROLE{ - ADMIN, MANAGER, TESTER, PARTICIPANT + ADMIN, MANAGER, USER } private ROLE role; - private String region; - private Integer exp; - private Integer level; - private String type; - - private String curProductRegion; - - private boolean isValid; - private String refreshToken; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") @Column(name = "created_at") private Timestamp createdAt; + + public String getRoleName() { + return "ROLE_" + this.role.name(); + } + } \ No newline at end of file diff --git a/src/main/java/com/ns/solve/Domain/dto/KakaoProfile.java b/src/main/java/com/ns/solve/Domain/dto/KakaoProfile.java new file mode 100644 index 0000000..3bd1872 --- /dev/null +++ b/src/main/java/com/ns/solve/Domain/dto/KakaoProfile.java @@ -0,0 +1,42 @@ +package com.ns.solve.Domain.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +@Data +public class KakaoProfile { + public Long id; + public String connected_at; + public Properties properties; + public Kakao_Account kakao_account; + + @Data + @JsonIgnoreProperties(ignoreUnknown=true) + public class Properties { + + public String nickname; + + } + @Data + @JsonIgnoreProperties(ignoreUnknown=true) + public class Kakao_Account { + + public Boolean profile_nickname_needs_agreement; + public Profile profile; + public Boolean has_email; + public Boolean email_Needs_Agreement; + public Boolean is_Email_Valid; + public Boolean is_Email_Verified; + public String email; + + @Data + @JsonIgnoreProperties(ignoreUnknown=true) + public class Profile { + + public String nickname; + + } + + } + +} diff --git a/src/main/java/com/ns/solve/Domain/dto/KakaoRequest.java b/src/main/java/com/ns/solve/Domain/dto/KakaoRequest.java new file mode 100644 index 0000000..720f452 --- /dev/null +++ b/src/main/java/com/ns/solve/Domain/dto/KakaoRequest.java @@ -0,0 +1,7 @@ +package com.ns.solve.Domain.dto; + +import lombok.Data; +@Data +public class KakaoRequest { + private String access_token; +} \ No newline at end of file diff --git a/src/main/java/com/ns/solve/Domain/dto/KakaoToken.java b/src/main/java/com/ns/solve/Domain/dto/KakaoToken.java new file mode 100644 index 0000000..1039dd0 --- /dev/null +++ b/src/main/java/com/ns/solve/Domain/dto/KakaoToken.java @@ -0,0 +1,13 @@ +package com.ns.solve.Domain.dto; + +import lombok.Data; +@Data +public class KakaoToken { + private String access_token; + private String token_type; + private String refresh_token; + private String id_token; + private int expires_in; + private String scope; + private int refresh_token_expires_in; +} diff --git a/src/main/java/com/ns/solve/Domain/dto/MessageEntity.java b/src/main/java/com/ns/solve/Domain/dto/MessageEntity.java new file mode 100644 index 0000000..29acc44 --- /dev/null +++ b/src/main/java/com/ns/solve/Domain/dto/MessageEntity.java @@ -0,0 +1,14 @@ +package com.ns.solve.Domain.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +@AllArgsConstructor +public class MessageEntity { + + private String message; + private Object result; +} \ No newline at end of file diff --git a/src/main/java/com/ns/solve/Repository/MembershipCustomRepository.java b/src/main/java/com/ns/solve/Repository/MembershipCustomRepository.java index 62af39b..afddd7a 100644 --- a/src/main/java/com/ns/solve/Repository/MembershipCustomRepository.java +++ b/src/main/java/com/ns/solve/Repository/MembershipCustomRepository.java @@ -5,4 +5,5 @@ public interface MembershipCustomRepository { Optional findByMembershipId(Long membershipId); + Optional findByAccount(String membershipAccount); } diff --git a/src/main/java/com/ns/solve/Repository/MembershipCustomRepositoryImpl.java b/src/main/java/com/ns/solve/Repository/MembershipCustomRepositoryImpl.java index 456e983..027ece9 100644 --- a/src/main/java/com/ns/solve/Repository/MembershipCustomRepositoryImpl.java +++ b/src/main/java/com/ns/solve/Repository/MembershipCustomRepositoryImpl.java @@ -20,4 +20,9 @@ public MembershipCustomRepositoryImpl(JPAQueryFactory jpaQueryFactory, QMembersh public Optional findByMembershipId(Long membershipId) { return Optional.empty(); } + + @Override + public Optional findByAccount(String membershipAccount) { + return null; + } } diff --git a/src/main/java/com/ns/solve/Service/MembershipService.java b/src/main/java/com/ns/solve/Service/MembershipService.java index 074fe30..94515ad 100644 --- a/src/main/java/com/ns/solve/Service/MembershipService.java +++ b/src/main/java/com/ns/solve/Service/MembershipService.java @@ -2,6 +2,7 @@ import com.ns.solve.Domain.Membership; import com.ns.solve.Repository.MembershipRepository; +import com.ns.solve.Utils.JwtToken; import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,6 +12,9 @@ public class MembershipService { private final MembershipRepository membershipRepository; + public JwtToken LoginMembership(Long membershipId){ + return null; + } private Optional findByMembershipId(Long membershipId){ return membershipRepository.findByMembershipId(membershipId); diff --git a/src/main/java/com/ns/solve/Utils/JwtToken.java b/src/main/java/com/ns/solve/Utils/JwtToken.java new file mode 100644 index 0000000..bf46842 --- /dev/null +++ b/src/main/java/com/ns/solve/Utils/JwtToken.java @@ -0,0 +1,27 @@ +package com.ns.solve.Utils; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class JwtToken { + + @Getter + private final Long membershipId; + @Getter + private final String jwtToken; + @Getter + private final String refreshToken; + + + public static JwtToken generateJwtToken(Long membershipId, String membershipJwtToken, + String membershipRefreshToken) { + + return new JwtToken( + membershipId, membershipJwtToken, membershipRefreshToken + ); + } + + +} diff --git a/src/main/java/com/ns/solve/Utils/JwtTokenProvider.java b/src/main/java/com/ns/solve/Utils/JwtTokenProvider.java new file mode 100644 index 0000000..926b0cc --- /dev/null +++ b/src/main/java/com/ns/solve/Utils/JwtTokenProvider.java @@ -0,0 +1,4 @@ +package com.ns.solve.Utils; + +public class JwtTokenProvider { +}