From c34232798c2e11c9f27a992b8354edbd225e0609 Mon Sep 17 00:00:00 2001
From: Jonghak Choi <105853600+JongHak19@users.noreply.github.com>
Date: Fri, 30 Jun 2023 12:27:05 +0900
Subject: [PATCH 1/9] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index dd10ef6..df20356 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ http://localhost:8080/swagger-ui/index.html
| 김남주 | 박상현 | 엄예진 | 최종학 |
| :------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------: |
|
|
|
|
|
-| [cmsong111](https://github.com/cmsong111) | [thelight0804](https://github.com/thelight0804) | [yejin-e](https://github.com/yejin-e) | |
+| [cmsong111](https://github.com/cmsong111) | [thelight0804](https://github.com/thelight0804) | [yejin-e](https://github.com/yejin-e) | [JongHak19](https://github.com/JongHak19) |
## 라이선스
From 9b151c585be5d917347027dc09186a2982bec8da Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 3 Jul 2023 03:53:52 +0900
Subject: [PATCH 2/9] =?UTF-8?q?user=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?=
=?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/com/gdsc/blog/user/user.java | 49 ++++++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 src/main/java/com/gdsc/blog/user/user.java
diff --git a/src/main/java/com/gdsc/blog/user/user.java b/src/main/java/com/gdsc/blog/user/user.java
new file mode 100644
index 0000000..57d821d
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/user/user.java
@@ -0,0 +1,49 @@
+package com.gdsc.blog.user;
+
+public class user {
+ private String ID;
+ private String password;
+ private String address;
+ private String phone;
+ private String gender;
+
+ public String getID() {
+ return ID;
+ }
+
+ public void setID(String ID) {
+ this.ID = ID;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getGender() {
+ return gender;
+ }
+
+ public void setGender(String gender) {
+ this.gender = gender;
+ }
+}
From ff5d1f5eda56bf63006f359c18f7ee7ecddcb5e2 Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 3 Jul 2023 10:01:54 +0900
Subject: [PATCH 3/9] =?UTF-8?q?user=20=EB=A0=88=ED=8C=8C=EC=A7=80=ED=86=A0?=
=?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1,=20=EB=B0=8F=20=ED=85=8C?=
=?UTF-8?q?=EC=8A=A4=ED=8A=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/gdsc/blog/SwaggerConfig.java | 24 +++++++++++++++++++
.../blog/user/{user.java => Customer.java} | 10 +++++---
.../java/com/gdsc/blog/user/UserService.java | 7 ++++++
.../com/gdsc/blog/user/userController.java | 10 ++++++++
.../com/gdsc/blog/user/userRepository.java | 7 ++++++
.../com/gdsc/blog/BlogApplicationTests.java | 14 ++++++++---
6 files changed, 66 insertions(+), 6 deletions(-)
create mode 100644 src/main/java/com/gdsc/blog/SwaggerConfig.java
rename src/main/java/com/gdsc/blog/user/{user.java => Customer.java} (89%)
create mode 100644 src/main/java/com/gdsc/blog/user/UserService.java
create mode 100644 src/main/java/com/gdsc/blog/user/userController.java
create mode 100644 src/main/java/com/gdsc/blog/user/userRepository.java
diff --git a/src/main/java/com/gdsc/blog/SwaggerConfig.java b/src/main/java/com/gdsc/blog/SwaggerConfig.java
new file mode 100644
index 0000000..c6e55c5
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/SwaggerConfig.java
@@ -0,0 +1,24 @@
+package com.gdsc.blog;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+
+public class SwaggerConfig {
+
+ private Set getConsumeContentTypes() {
+ Set consumes = new HashSet<>();
+ consumes.add("application/json;charset=UTF-8");
+ consumes.add("application/x-www-form-urlencoded");
+ return consumes;
+ }
+
+ private Set getProduceContentTypes() {
+ Set produces = new HashSet<>();
+ produces.add("application/json;charset=UTF-8");
+ return produces;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/gdsc/blog/user/user.java b/src/main/java/com/gdsc/blog/user/Customer.java
similarity index 89%
rename from src/main/java/com/gdsc/blog/user/user.java
rename to src/main/java/com/gdsc/blog/user/Customer.java
index 57d821d..310b9bd 100644
--- a/src/main/java/com/gdsc/blog/user/user.java
+++ b/src/main/java/com/gdsc/blog/user/Customer.java
@@ -1,7 +1,13 @@
package com.gdsc.blog.user;
-public class user {
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+
+@Entity
+public class Customer {
+ @Id
private String ID;
+
private String password;
private String address;
private String phone;
@@ -10,11 +16,9 @@ public class user {
public String getID() {
return ID;
}
-
public void setID(String ID) {
this.ID = ID;
}
-
public String getPassword() {
return password;
}
diff --git a/src/main/java/com/gdsc/blog/user/UserService.java b/src/main/java/com/gdsc/blog/user/UserService.java
new file mode 100644
index 0000000..ccc3442
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/user/UserService.java
@@ -0,0 +1,7 @@
+package com.gdsc.blog.user;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class UserService {
+}
diff --git a/src/main/java/com/gdsc/blog/user/userController.java b/src/main/java/com/gdsc/blog/user/userController.java
new file mode 100644
index 0000000..b1d2aec
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/user/userController.java
@@ -0,0 +1,10 @@
+package com.gdsc.blog.user;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RequestMapping("/user")
+@Controller
+public class userController {
+
+}
diff --git a/src/main/java/com/gdsc/blog/user/userRepository.java b/src/main/java/com/gdsc/blog/user/userRepository.java
new file mode 100644
index 0000000..c1fa8ae
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/user/userRepository.java
@@ -0,0 +1,7 @@
+package com.gdsc.blog.user;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface userRepository extends JpaRepository {
+
+}
diff --git a/src/test/java/com/gdsc/blog/BlogApplicationTests.java b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
index 533a031..86cfee0 100644
--- a/src/test/java/com/gdsc/blog/BlogApplicationTests.java
+++ b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
@@ -1,14 +1,22 @@
package com.gdsc.blog;
+import com.gdsc.blog.user.Customer;
+import com.gdsc.blog.user.userRepository;
import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Profile;
@SpringBootTest
@Profile("test")
class BlogApplicationTests {
-
+ @Autowired
+ userRepository userRepository;
@Test
- void contextLoads() {}
-
+ void testJoin() {
+ Customer user1 = new Customer();
+ user1.setID("cj8556");
+ user1.setPassword("test1234");
+ this.userRepository.save(user1);
+ }
}
From 68a2ca99c3403a92f1b177a054792073b245ef23 Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 3 Jul 2023 11:45:51 +0900
Subject: [PATCH 4/9] =?UTF-8?q?=EC=8B=9C=ED=81=90=EB=A6=AC=ED=8B=B0=20?=
=?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/gdsc/blog/SecurityConfig.java | 20 +++++++
.../java/com/gdsc/blog/user/Customer.java | 53 -------------------
src/main/java/com/gdsc/blog/user/Member.java | 20 +++++++
.../com/gdsc/blog/user/MemberController.java | 18 +++++++
...rRepository.java => MemberRepository.java} | 2 +-
.../com/gdsc/blog/user/MemberService.java | 24 +++++++++
.../java/com/gdsc/blog/user/UserService.java | 7 ---
.../com/gdsc/blog/user/userController.java | 10 ----
.../com/gdsc/blog/BlogApplicationTests.java | 23 ++++++--
9 files changed, 102 insertions(+), 75 deletions(-)
create mode 100644 src/main/java/com/gdsc/blog/SecurityConfig.java
delete mode 100644 src/main/java/com/gdsc/blog/user/Customer.java
create mode 100644 src/main/java/com/gdsc/blog/user/Member.java
create mode 100644 src/main/java/com/gdsc/blog/user/MemberController.java
rename src/main/java/com/gdsc/blog/user/{userRepository.java => MemberRepository.java} (62%)
create mode 100644 src/main/java/com/gdsc/blog/user/MemberService.java
delete mode 100644 src/main/java/com/gdsc/blog/user/UserService.java
delete mode 100644 src/main/java/com/gdsc/blog/user/userController.java
diff --git a/src/main/java/com/gdsc/blog/SecurityConfig.java b/src/main/java/com/gdsc/blog/SecurityConfig.java
new file mode 100644
index 0000000..0caabde
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/SecurityConfig.java
@@ -0,0 +1,20 @@
+package com.gdsc.blog;
+
+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.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig {
+ @Bean
+ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+ http.authorizeRequests().requestMatchers( //authorizeHttpRequests -> authorizeRequests
+ new AntPathRequestMatcher("/**")).permitAll()
+ ;
+ return http.build();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gdsc/blog/user/Customer.java b/src/main/java/com/gdsc/blog/user/Customer.java
deleted file mode 100644
index 310b9bd..0000000
--- a/src/main/java/com/gdsc/blog/user/Customer.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.gdsc.blog.user;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-
-@Entity
-public class Customer {
- @Id
- private String ID;
-
- private String password;
- private String address;
- private String phone;
- private String gender;
-
- public String getID() {
- return ID;
- }
- public void setID(String ID) {
- this.ID = ID;
- }
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public String getAddress() {
- return address;
- }
-
- public void setAddress(String address) {
- this.address = address;
- }
-
- public String getPhone() {
- return phone;
- }
-
- public void setPhone(String phone) {
- this.phone = phone;
- }
-
- public String getGender() {
- return gender;
- }
-
- public void setGender(String gender) {
- this.gender = gender;
- }
-}
diff --git a/src/main/java/com/gdsc/blog/user/Member.java b/src/main/java/com/gdsc/blog/user/Member.java
new file mode 100644
index 0000000..9f0d157
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/user/Member.java
@@ -0,0 +1,20 @@
+package com.gdsc.blog.user;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import lombok.Getter;
+import lombok.Setter;
+
+@Entity
+@Getter
+@Setter
+public class Member {
+ @Id
+ private String ID;
+
+ private String password;
+ private String phone;
+ @Column(unique = true)
+ private String email;
+}
diff --git a/src/main/java/com/gdsc/blog/user/MemberController.java b/src/main/java/com/gdsc/blog/user/MemberController.java
new file mode 100644
index 0000000..89a2fc1
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/user/MemberController.java
@@ -0,0 +1,18 @@
+package com.gdsc.blog.user;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@RequestMapping("/user")
+@Controller
+public class MemberController {
+
+ @GetMapping("/login")
+ @ResponseBody
+ public String loginUI(){
+ return "login 접근 성공";
+ }
+
+}
diff --git a/src/main/java/com/gdsc/blog/user/userRepository.java b/src/main/java/com/gdsc/blog/user/MemberRepository.java
similarity index 62%
rename from src/main/java/com/gdsc/blog/user/userRepository.java
rename to src/main/java/com/gdsc/blog/user/MemberRepository.java
index c1fa8ae..26cf022 100644
--- a/src/main/java/com/gdsc/blog/user/userRepository.java
+++ b/src/main/java/com/gdsc/blog/user/MemberRepository.java
@@ -2,6 +2,6 @@
import org.springframework.data.jpa.repository.JpaRepository;
-public interface userRepository extends JpaRepository {
+public interface MemberRepository extends JpaRepository {
}
diff --git a/src/main/java/com/gdsc/blog/user/MemberService.java b/src/main/java/com/gdsc/blog/user/MemberService.java
new file mode 100644
index 0000000..ea2bac8
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/user/MemberService.java
@@ -0,0 +1,24 @@
+package com.gdsc.blog.user;
+
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MemberService {
+ private final MemberRepository memberRepository;
+
+ public MemberService(MemberRepository memberRepository) {
+ this.memberRepository = memberRepository;
+ }
+
+ public Member create(String ID, String pwd, String phone, String email){
+ Member member = new Member();
+ member.setID(ID);
+ member.setPhone(phone);
+ member.setEmail(email);
+ BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+ member.setPassword(passwordEncoder.encode(pwd));
+ this.memberRepository.save(member);
+ return member;
+ }
+}
diff --git a/src/main/java/com/gdsc/blog/user/UserService.java b/src/main/java/com/gdsc/blog/user/UserService.java
deleted file mode 100644
index ccc3442..0000000
--- a/src/main/java/com/gdsc/blog/user/UserService.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.gdsc.blog.user;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class UserService {
-}
diff --git a/src/main/java/com/gdsc/blog/user/userController.java b/src/main/java/com/gdsc/blog/user/userController.java
deleted file mode 100644
index b1d2aec..0000000
--- a/src/main/java/com/gdsc/blog/user/userController.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.gdsc.blog.user;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-@RequestMapping("/user")
-@Controller
-public class userController {
-
-}
diff --git a/src/test/java/com/gdsc/blog/BlogApplicationTests.java b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
index 86cfee0..bc5a3a3 100644
--- a/src/test/java/com/gdsc/blog/BlogApplicationTests.java
+++ b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
@@ -1,22 +1,37 @@
package com.gdsc.blog;
-import com.gdsc.blog.user.Customer;
-import com.gdsc.blog.user.userRepository;
+import com.gdsc.blog.user.Member;
+import com.gdsc.blog.user.MemberRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Profile;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
@SpringBootTest
@Profile("test")
class BlogApplicationTests {
@Autowired
- userRepository userRepository;
+ MemberRepository userRepository;
@Test
void testJoin() {
- Customer user1 = new Customer();
+ Member user1 = new Member();
user1.setID("cj8556");
user1.setPassword("test1234");
this.userRepository.save(user1);
+
+ Optional oq = this.userRepository.findById("cj8556");
+ if(oq.isPresent()) {
+ Member q = oq.get();
+ assertEquals("cj8556", q.getID());
+ }
+ }
+
+ @Test
+ void testGetInformation() {
+
}
}
From 8eb7b80e47b00d89172ab45a7c499113c8a84823 Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 3 Jul 2023 15:14:00 +0900
Subject: [PATCH 5/9] =?UTF-8?q?jwt=20=ED=94=84=EB=A1=9C=EB=B0=94=EC=9D=B4?=
=?UTF-8?q?=EB=8D=94=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=9A=8C=EC=9B=90?=
=?UTF-8?q?=EA=B0=80=EC=9E=85=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?=
=?UTF-8?q?-=20swagger=EC=97=90=EC=84=9C=20=ED=99=95=EC=9D=B8=20=EB=B6=88?=
=?UTF-8?q?=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
build.gradle | 4 ++
.../java/com/gdsc/blog/JwtTokenProvider.java | 44 +++++++++++++++++++
.../java/com/gdsc/blog/SecurityConfig.java | 7 +++
.../com/gdsc/blog/user/MemberController.java | 20 +++++++--
.../com/gdsc/blog/user/MemberRepository.java | 1 -
.../com/gdsc/blog/user/MemberService.java | 29 ++++++++----
6 files changed, 91 insertions(+), 14 deletions(-)
create mode 100644 src/main/java/com/gdsc/blog/JwtTokenProvider.java
diff --git a/build.gradle b/build.gradle
index 58781da..2c6c90e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -31,6 +31,10 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.mariadb.jdbc:mariadb-java-client:3.1.4'
+
+ //JWT
+ implementation 'io.jsonwebtoken:jjwt:0.9.1' //jjwt 의존성 추가
+
implementation 'com.h2database:h2:2.1.214' // TODO : testimplementation으로 변경
}
diff --git a/src/main/java/com/gdsc/blog/JwtTokenProvider.java b/src/main/java/com/gdsc/blog/JwtTokenProvider.java
new file mode 100644
index 0000000..8dccbd8
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/JwtTokenProvider.java
@@ -0,0 +1,44 @@
+package com.gdsc.blog;
+
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+@Service
+public class JwtTokenProvider {
+
+ private static final long EXPIRATION_TIME = 864_000_000; // 10일
+ private static final String secretKey = "user"; // 임의의 비밀키 문자열
+
+ public String generateToken(Authentication authentication) {
+ UserDetails userPrincipal = (UserDetails) authentication.getPrincipal();
+ Date now = new Date();
+ Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME);
+
+ return Jwts.builder()
+ .setSubject(userPrincipal.getUsername())
+ .setIssuedAt(new Date())
+ .setExpiration(expiryDate)
+ .signWith(SignatureAlgorithm.HS256, secretKey.getBytes())
+ .compact();
+ }
+
+ public boolean validateToken(String token) {
+ try {
+ Jwts.parser().setSigningKey(secretKey.getBytes()).parseClaimsJws(token);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public String getUserIdFromJWT(String token) {
+ return Jwts.parser().setSigningKey(secretKey.getBytes()).parseClaimsJws(token).getBody().getSubject();
+ }
+
+}
diff --git a/src/main/java/com/gdsc/blog/SecurityConfig.java b/src/main/java/com/gdsc/blog/SecurityConfig.java
index 0caabde..6d5f882 100644
--- a/src/main/java/com/gdsc/blog/SecurityConfig.java
+++ b/src/main/java/com/gdsc/blog/SecurityConfig.java
@@ -4,6 +4,8 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@@ -17,4 +19,9 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
;
return http.build();
}
+
+ @Bean
+ PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/gdsc/blog/user/MemberController.java b/src/main/java/com/gdsc/blog/user/MemberController.java
index 89a2fc1..8fdae5b 100644
--- a/src/main/java/com/gdsc/blog/user/MemberController.java
+++ b/src/main/java/com/gdsc/blog/user/MemberController.java
@@ -1,18 +1,30 @@
package com.gdsc.blog.user;
+import com.gdsc.blog.JwtTokenProvider;
+import io.swagger.v3.oas.annotations.Operation;
+import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.*;
@RequestMapping("/user")
@Controller
public class MemberController {
+ private MemberService memberService;
+ private JwtTokenProvider tokenProvider;
+
+ public MemberController(MemberService memberService, JwtTokenProvider tokenProvider) {
+ this.memberService = memberService;
+ this.tokenProvider = tokenProvider;
+ }
+
@GetMapping("/login")
@ResponseBody
public String loginUI(){
return "login 접근 성공";
}
-
+ @PostMapping("/register")
+ public ResponseEntity> register(@RequestBody Member member){
+ return ResponseEntity.ok(memberService.register(member));
+ }
}
diff --git a/src/main/java/com/gdsc/blog/user/MemberRepository.java b/src/main/java/com/gdsc/blog/user/MemberRepository.java
index 26cf022..6d0e558 100644
--- a/src/main/java/com/gdsc/blog/user/MemberRepository.java
+++ b/src/main/java/com/gdsc/blog/user/MemberRepository.java
@@ -3,5 +3,4 @@
import org.springframework.data.jpa.repository.JpaRepository;
public interface MemberRepository extends JpaRepository {
-
}
diff --git a/src/main/java/com/gdsc/blog/user/MemberService.java b/src/main/java/com/gdsc/blog/user/MemberService.java
index ea2bac8..e983f4a 100644
--- a/src/main/java/com/gdsc/blog/user/MemberService.java
+++ b/src/main/java/com/gdsc/blog/user/MemberService.java
@@ -1,24 +1,35 @@
package com.gdsc.blog.user;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
+import java.util.Optional;
+
@Service
public class MemberService {
private final MemberRepository memberRepository;
+ private final PasswordEncoder passwordEncoder;
+
- public MemberService(MemberRepository memberRepository) {
+ public MemberService(MemberRepository memberRepository, PasswordEncoder passwordEncoder) {
this.memberRepository = memberRepository;
+ this.passwordEncoder = passwordEncoder;
}
- public Member create(String ID, String pwd, String phone, String email){
- Member member = new Member();
- member.setID(ID);
- member.setPhone(phone);
- member.setEmail(email);
- BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
- member.setPassword(passwordEncoder.encode(pwd));
+ public Member register(Member member){
+ member.setID(member.getID());
+ member.setPhone(member.getPhone());
+ member.setEmail(member.getEmail());
+ member.setPassword(passwordEncoder.encode(member.getPassword()));
this.memberRepository.save(member);
return member;
}
+ public Member login(String ID, String pwd){
+ Optional member = memberRepository.findById(ID);
+ if(member != null && passwordEncoder.matches(pwd, member.get().getPassword())){
+ return member.get();
+ }
+ else
+ return null;
+ }
}
From 192cf2c7ff9e830781c5acc941dc158b686baba8 Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 3 Jul 2023 17:36:37 +0900
Subject: [PATCH 6/9] =?UTF-8?q?swagger=20ui=EC=97=90=20login=EC=9D=80=20?=
=?UTF-8?q?=ED=91=9C=EC=8B=9C=EB=90=98=EB=82=98=20register(=ED=9A=8C?=
=?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=20=ED=91=9C=EC=8B=9Cx)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
build.gradle | 4 +++-
.../java/com/gdsc/blog/SecurityConfig.java | 3 +--
.../java/com/gdsc/blog/SwaggerConfig.java | 24 -------------------
src/main/java/com/gdsc/blog/user/Member.java | 1 -
.../com/gdsc/blog/user/MemberController.java | 19 +++++++++------
5 files changed, 16 insertions(+), 35 deletions(-)
delete mode 100644 src/main/java/com/gdsc/blog/SwaggerConfig.java
diff --git a/build.gradle b/build.gradle
index 2c6c90e..9548bf7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,7 +25,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
+ //swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
+
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
@@ -34,7 +36,7 @@ dependencies {
//JWT
implementation 'io.jsonwebtoken:jjwt:0.9.1' //jjwt 의존성 추가
-
+ //implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'com.h2database:h2:2.1.214' // TODO : testimplementation으로 변경
}
diff --git a/src/main/java/com/gdsc/blog/SecurityConfig.java b/src/main/java/com/gdsc/blog/SecurityConfig.java
index 6d5f882..e83633e 100644
--- a/src/main/java/com/gdsc/blog/SecurityConfig.java
+++ b/src/main/java/com/gdsc/blog/SecurityConfig.java
@@ -15,8 +15,7 @@ public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().requestMatchers( //authorizeHttpRequests -> authorizeRequests
- new AntPathRequestMatcher("/**")).permitAll()
- ;
+ new AntPathRequestMatcher("/**")).permitAll();
return http.build();
}
diff --git a/src/main/java/com/gdsc/blog/SwaggerConfig.java b/src/main/java/com/gdsc/blog/SwaggerConfig.java
deleted file mode 100644
index c6e55c5..0000000
--- a/src/main/java/com/gdsc/blog/SwaggerConfig.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.gdsc.blog;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-
-public class SwaggerConfig {
-
- private Set getConsumeContentTypes() {
- Set consumes = new HashSet<>();
- consumes.add("application/json;charset=UTF-8");
- consumes.add("application/x-www-form-urlencoded");
- return consumes;
- }
-
- private Set getProduceContentTypes() {
- Set produces = new HashSet<>();
- produces.add("application/json;charset=UTF-8");
- return produces;
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/com/gdsc/blog/user/Member.java b/src/main/java/com/gdsc/blog/user/Member.java
index 9f0d157..17c4d64 100644
--- a/src/main/java/com/gdsc/blog/user/Member.java
+++ b/src/main/java/com/gdsc/blog/user/Member.java
@@ -12,7 +12,6 @@
public class Member {
@Id
private String ID;
-
private String password;
private String phone;
@Column(unique = true)
diff --git a/src/main/java/com/gdsc/blog/user/MemberController.java b/src/main/java/com/gdsc/blog/user/MemberController.java
index 8fdae5b..7d62a51 100644
--- a/src/main/java/com/gdsc/blog/user/MemberController.java
+++ b/src/main/java/com/gdsc/blog/user/MemberController.java
@@ -1,7 +1,6 @@
package com.gdsc.blog.user;
import com.gdsc.blog.JwtTokenProvider;
-import io.swagger.v3.oas.annotations.Operation;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@@ -12,19 +11,25 @@ public class MemberController {
private MemberService memberService;
private JwtTokenProvider tokenProvider;
-
public MemberController(MemberService memberService, JwtTokenProvider tokenProvider) {
this.memberService = memberService;
this.tokenProvider = tokenProvider;
}
- @GetMapping("/login")
+ @GetMapping("/login_ok")
+ @ResponseBody
+ public String login_ok(){
+ return "로그인 성공";
+ }
+ @PostMapping("/login")
@ResponseBody
- public String loginUI(){
- return "login 접근 성공";
+ public String login(@RequestBody String ID, String pwd){
+ memberService.login(ID, pwd);
+ return "redirect:/user/login_ok";
}
@PostMapping("/register")
- public ResponseEntity> register(@RequestBody Member member){
- return ResponseEntity.ok(memberService.register(member));
+ public String register(@RequestBody Member member){
+ ResponseEntity.ok(memberService.register(member));
+ return "redirect:/user/login";
}
}
From 1b54fa29bcc61446429a8fcaa918b480df47b17f Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 3 Jul 2023 17:50:26 +0900
Subject: [PATCH 7/9] =?UTF-8?q?swagger=20=EC=84=A4=EC=A0=95=20=EC=82=AD?=
=?UTF-8?q?=EC=A0=9C(=EB=B3=B5=EC=9B=90)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/.gitignore | 8 ++++++++
.idea/.name | 1 +
.idea/compiler.xml | 16 +++++++++++++++
.idea/jarRepositories.xml | 20 +++++++++++++++++++
.idea/misc.xml | 8 ++++++++
.idea/vcs.xml | 6 ++++++
build.gradle | 1 +
.../com/gdsc/blog/BlogApplicationTests.java | 2 +-
8 files changed, 61 insertions(+), 1 deletion(-)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/.name
create mode 100644 .idea/compiler.xml
create mode 100644 .idea/jarRepositories.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/vcs.xml
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..0d50744
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+blog
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..2fc4ea3
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..fdc392f
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..de0c428
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 9548bf7..668d9e7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -27,6 +27,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
//swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
+ //implementation 'io.springfox:springfox-boot-starter:3.0.0' //swagger로 회원가입 API(post)가 표시되게 하기위해 추가
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
diff --git a/src/test/java/com/gdsc/blog/BlogApplicationTests.java b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
index bc5a3a3..a54af91 100644
--- a/src/test/java/com/gdsc/blog/BlogApplicationTests.java
+++ b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
@@ -17,7 +17,7 @@ class BlogApplicationTests {
@Autowired
MemberRepository userRepository;
@Test
- void testJoin() {
+ void testJoin() { //회원가입 테스트
Member user1 = new Member();
user1.setID("cj8556");
user1.setPassword("test1234");
From f2738fa49b01cc46bf1d07c9ae2659a2898a4f13 Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 3 Jul 2023 20:34:03 +0900
Subject: [PATCH 8/9] =?UTF-8?q?security=20=EC=84=A4=EC=A0=95=20csrf=20?=
=?UTF-8?q?=EB=B3=B4=ED=98=B8=20=EC=A0=9C=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/com/gdsc/blog/SecurityConfig.java | 4 +++-
src/main/java/com/gdsc/blog/user/MemberController.java | 5 +++--
src/main/java/com/gdsc/blog/user/MemberService.java | 2 +-
src/test/java/com/gdsc/blog/BlogApplicationTests.java | 1 +
4 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/main/java/com/gdsc/blog/SecurityConfig.java b/src/main/java/com/gdsc/blog/SecurityConfig.java
index e83633e..fcb259b 100644
--- a/src/main/java/com/gdsc/blog/SecurityConfig.java
+++ b/src/main/java/com/gdsc/blog/SecurityConfig.java
@@ -15,7 +15,9 @@ public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().requestMatchers( //authorizeHttpRequests -> authorizeRequests
- new AntPathRequestMatcher("/**")).permitAll();
+ new AntPathRequestMatcher("/**")).permitAll()
+ .and()
+ .csrf(csrf->csrf.disable());
return http.build();
}
diff --git a/src/main/java/com/gdsc/blog/user/MemberController.java b/src/main/java/com/gdsc/blog/user/MemberController.java
index 7d62a51..7a878c2 100644
--- a/src/main/java/com/gdsc/blog/user/MemberController.java
+++ b/src/main/java/com/gdsc/blog/user/MemberController.java
@@ -23,11 +23,12 @@ public String login_ok(){
}
@PostMapping("/login")
@ResponseBody
- public String login(@RequestBody String ID, String pwd){
- memberService.login(ID, pwd);
+ public String login(@RequestBody Member member){
+ memberService.login(member.getID(), member.getPassword());
return "redirect:/user/login_ok";
}
@PostMapping("/register")
+ @ResponseBody
public String register(@RequestBody Member member){
ResponseEntity.ok(memberService.register(member));
return "redirect:/user/login";
diff --git a/src/main/java/com/gdsc/blog/user/MemberService.java b/src/main/java/com/gdsc/blog/user/MemberService.java
index e983f4a..55c00a2 100644
--- a/src/main/java/com/gdsc/blog/user/MemberService.java
+++ b/src/main/java/com/gdsc/blog/user/MemberService.java
@@ -8,7 +8,7 @@
@Service
public class MemberService {
private final MemberRepository memberRepository;
- private final PasswordEncoder passwordEncoder;
+ private final PasswordEncoder passwordEncoder; //비밀번호 암호화
public MemberService(MemberRepository memberRepository, PasswordEncoder passwordEncoder) {
diff --git a/src/test/java/com/gdsc/blog/BlogApplicationTests.java b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
index a54af91..4c1d341 100644
--- a/src/test/java/com/gdsc/blog/BlogApplicationTests.java
+++ b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
@@ -27,6 +27,7 @@ void testJoin() { //회원가입 테스트
if(oq.isPresent()) {
Member q = oq.get();
assertEquals("cj8556", q.getID());
+ assertEquals("test1234",q.getPassword());
}
}
From a942884de578a805c79cfb4998cd14a00875f6d9 Mon Sep 17 00:00:00 2001
From: master
Date: Mon, 10 Jul 2023 04:08:01 +0900
Subject: [PATCH 9/9] Article CRUD
---
build.gradle | 4 +-
.../java/com/gdsc/blog/JwtTokenProvider.java | 44 ---------
.../java/com/gdsc/blog/SecurityConfig.java | 28 ------
.../article/controller/ArticleController.java | 92 +++++++++++++++++++
.../com/gdsc/blog/article/dto/CreateDto.java | 18 ++++
.../com/gdsc/blog/article/dto/UpdateDto.java | 18 ++++
.../com/gdsc/blog/article/entity/Article.java | 33 +++++++
.../article/repository/ArticleRepository.java | 8 ++
.../blog/article/service/ArticleService.java | 74 +++++++++++++++
.../blog/configuration/SecurityConfig.java | 3 +-
.../blog/security/jwt/JwtTokenFilter.java | 16 +++-
src/main/java/com/gdsc/blog/user/Member.java | 19 ----
.../com/gdsc/blog/user/MemberController.java | 36 --------
.../com/gdsc/blog/user/MemberRepository.java | 6 --
.../com/gdsc/blog/user/MemberService.java | 35 -------
.../blog/user/controller/UserController.java | 6 +-
.../java/com/gdsc/blog/user/entity/User.java | 20 ++--
.../gdsc/blog/user/service/UserService.java | 41 +++++++--
.../com/gdsc/blog/BlogApplicationTests.java | 16 +---
19 files changed, 303 insertions(+), 214 deletions(-)
delete mode 100644 src/main/java/com/gdsc/blog/JwtTokenProvider.java
delete mode 100644 src/main/java/com/gdsc/blog/SecurityConfig.java
create mode 100644 src/main/java/com/gdsc/blog/article/controller/ArticleController.java
create mode 100644 src/main/java/com/gdsc/blog/article/dto/CreateDto.java
create mode 100644 src/main/java/com/gdsc/blog/article/dto/UpdateDto.java
create mode 100644 src/main/java/com/gdsc/blog/article/entity/Article.java
create mode 100644 src/main/java/com/gdsc/blog/article/repository/ArticleRepository.java
create mode 100644 src/main/java/com/gdsc/blog/article/service/ArticleService.java
delete mode 100644 src/main/java/com/gdsc/blog/user/Member.java
delete mode 100644 src/main/java/com/gdsc/blog/user/MemberController.java
delete mode 100644 src/main/java/com/gdsc/blog/user/MemberRepository.java
delete mode 100644 src/main/java/com/gdsc/blog/user/MemberService.java
diff --git a/build.gradle b/build.gradle
index 1a15eef..d61a579 100644
--- a/build.gradle
+++ b/build.gradle
@@ -27,17 +27,15 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
//swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
- //implementation 'io.springfox:springfox-boot-starter:3.0.0' //swagger로 회원가입 API(post)가 표시되게 하기위해 추가
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.mariadb.jdbc:mariadb-java-client:3.1.4'
-
+ implementation 'javax.xml.bind:jaxb-api:2.3.0' //javax.xml.bind.JAXBException 에러 방지용
//JWT
implementation 'io.jsonwebtoken:jjwt:0.9.1' //jjwt 의존성 추가
- //implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'com.h2database:h2:2.1.214' // TODO : testimplementation으로 변경
implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
diff --git a/src/main/java/com/gdsc/blog/JwtTokenProvider.java b/src/main/java/com/gdsc/blog/JwtTokenProvider.java
deleted file mode 100644
index 8dccbd8..0000000
--- a/src/main/java/com/gdsc/blog/JwtTokenProvider.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.gdsc.blog;
-
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
-import org.springframework.context.annotation.Bean;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.stereotype.Service;
-
-import java.util.Date;
-
-@Service
-public class JwtTokenProvider {
-
- private static final long EXPIRATION_TIME = 864_000_000; // 10일
- private static final String secretKey = "user"; // 임의의 비밀키 문자열
-
- public String generateToken(Authentication authentication) {
- UserDetails userPrincipal = (UserDetails) authentication.getPrincipal();
- Date now = new Date();
- Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME);
-
- return Jwts.builder()
- .setSubject(userPrincipal.getUsername())
- .setIssuedAt(new Date())
- .setExpiration(expiryDate)
- .signWith(SignatureAlgorithm.HS256, secretKey.getBytes())
- .compact();
- }
-
- public boolean validateToken(String token) {
- try {
- Jwts.parser().setSigningKey(secretKey.getBytes()).parseClaimsJws(token);
- return true;
- } catch (Exception e) {
- return false;
- }
- }
-
- public String getUserIdFromJWT(String token) {
- return Jwts.parser().setSigningKey(secretKey.getBytes()).parseClaimsJws(token).getBody().getSubject();
- }
-
-}
diff --git a/src/main/java/com/gdsc/blog/SecurityConfig.java b/src/main/java/com/gdsc/blog/SecurityConfig.java
deleted file mode 100644
index fcb259b..0000000
--- a/src/main/java/com/gdsc/blog/SecurityConfig.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.gdsc.blog;
-
-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.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.security.web.SecurityFilterChain;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-
-@Configuration
-@EnableWebSecurity
-public class SecurityConfig {
- @Bean
- SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http.authorizeRequests().requestMatchers( //authorizeHttpRequests -> authorizeRequests
- new AntPathRequestMatcher("/**")).permitAll()
- .and()
- .csrf(csrf->csrf.disable());
- return http.build();
- }
-
- @Bean
- PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gdsc/blog/article/controller/ArticleController.java b/src/main/java/com/gdsc/blog/article/controller/ArticleController.java
new file mode 100644
index 0000000..d10608f
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/article/controller/ArticleController.java
@@ -0,0 +1,92 @@
+package com.gdsc.blog.article.controller;
+
+import com.gdsc.blog.article.dto.CreateDto;
+import com.gdsc.blog.article.dto.UpdateDto;
+import com.gdsc.blog.article.entity.Article;
+import com.gdsc.blog.article.service.ArticleService;
+import com.gdsc.blog.user.entity.User;
+import com.gdsc.blog.user.service.UserService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.crossstore.ChangeSetPersister;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.bind.annotation.*;
+
+import java.nio.file.AccessDeniedException;
+import java.util.List;
+
+@RestController
+@Slf4j
+@Tag(name = "Article", description = "Article API")
+@RequestMapping("/api/article")
+public class ArticleController {
+ private final ArticleService articleService; //private final로 안넣은 이유??
+ private final UserService userService;
+
+ public ArticleController(ArticleService articleService, UserService userService){
+ this.articleService = articleService;
+ this.userService = userService;
+ }
+
+ @PostMapping("/create")
+ @Operation(summary = "게시글 생성")
+ @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
+
+ public Article create(@RequestBody CreateDto article) {
+
+ Article article1 = Article.builder().subject(article.getSubject()).content(article.getContent()).build();
+
+ //현재 인증된 사용자 가져오기
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ String username = authentication.getName(); // 현재 인증된 사용자의 이름(아이디)를 가져온다.
+
+ User user = userService.getUserByName(username); // DB에서 사용자를 조회합니다.
+ return articleService.create(article1, user);
+ }
+ @GetMapping("/myallarticle") //내 게시글 목록
+ @Operation(summary = "내 게시글 목록")
+ @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
+ public List myallarticle(HttpServletRequest req) {
+ User user = userService.whoami(req);
+ return articleService.myAllArticle(user);
+ }
+
+ @GetMapping("article/{id}") // 특정 게시글
+ @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
+ @Operation(summary = "특정 게시글")
+ public Article getarticle(HttpServletRequest req, @PathVariable("id") Long id){
+ return articleService.getArticle(id);
+ }
+
+ @GetMapping("/allarticle") // 모든 게시글 조회
+ @Operation(summary = "모든 게시글 조회 ")
+ @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
+ public List allarticle(HttpServletRequest req) {
+ return articleService.getAllAriticle();
+ }
+
+ @PutMapping("/update/{id}")
+ @Operation(summary = "게시글 업데이트")
+ @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
+ public Article updateArticle(@PathVariable("id") Long id, @RequestBody UpdateDto article, HttpServletRequest req) throws ChangeSetPersister.NotFoundException, AccessDeniedException {
+ // 현재 인증된 사용자 가져오기
+ User user = userService.whoami(req);
+ Article updatedArticle = articleService.updateArticle(id, article, user);
+ return updatedArticle;
+ }
+
+ @DeleteMapping("/delete/{id}")
+ @Operation(summary = "게시글 삭제")
+ @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
+ public ResponseEntity> deleteArticle(@PathVariable("id") Long id, HttpServletRequest req) throws ChangeSetPersister.NotFoundException, AccessDeniedException {
+ // 현재 인증된 사용자 가져오기
+ User user = userService.whoami(req);
+ articleService.deleteArticle(id, user);
+ return ResponseEntity.ok().build();
+ }
+}
diff --git a/src/main/java/com/gdsc/blog/article/dto/CreateDto.java b/src/main/java/com/gdsc/blog/article/dto/CreateDto.java
new file mode 100644
index 0000000..b16a056
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/article/dto/CreateDto.java
@@ -0,0 +1,18 @@
+package com.gdsc.blog.article.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class CreateDto {
+ @Schema(description = "제목", example = "첫 게시글 입니다.")
+ public String subject;
+
+ @Schema(description = "내용", example = "안녕하세요.")
+ public String content;
+}
diff --git a/src/main/java/com/gdsc/blog/article/dto/UpdateDto.java b/src/main/java/com/gdsc/blog/article/dto/UpdateDto.java
new file mode 100644
index 0000000..1de63cf
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/article/dto/UpdateDto.java
@@ -0,0 +1,18 @@
+package com.gdsc.blog.article.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class UpdateDto {
+ @Schema(description = "제목", example = "수정될 제목")
+ public String subject;
+
+ @Schema(description = "내용", example = "수정될 내용")
+ public String content;
+}
\ No newline at end of file
diff --git a/src/main/java/com/gdsc/blog/article/entity/Article.java b/src/main/java/com/gdsc/blog/article/entity/Article.java
new file mode 100644
index 0000000..cfcce5d
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/article/entity/Article.java
@@ -0,0 +1,33 @@
+package com.gdsc.blog.article.entity;
+
+import com.fasterxml.jackson.annotation.JsonBackReference;
+import com.gdsc.blog.user.entity.User;
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Entity
+@Data
+@Builder //빌더 패턴을 사용
+@AllArgsConstructor //모든 필드를 매개변수로 받는 생성자
+@NoArgsConstructor //매개변수가 없는 기본 생성자
+public class Article {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long idx;
+
+ private String subject;
+
+ private String content;
+
+ private LocalDateTime createDate;
+
+ @JsonBackReference
+ @ManyToOne
+ private User user;
+}
diff --git a/src/main/java/com/gdsc/blog/article/repository/ArticleRepository.java b/src/main/java/com/gdsc/blog/article/repository/ArticleRepository.java
new file mode 100644
index 0000000..0fbfb74
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/article/repository/ArticleRepository.java
@@ -0,0 +1,8 @@
+package com.gdsc.blog.article.repository;
+
+import com.gdsc.blog.article.entity.Article;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+
+public interface ArticleRepository extends JpaRepository {
+}
diff --git a/src/main/java/com/gdsc/blog/article/service/ArticleService.java b/src/main/java/com/gdsc/blog/article/service/ArticleService.java
new file mode 100644
index 0000000..2615328
--- /dev/null
+++ b/src/main/java/com/gdsc/blog/article/service/ArticleService.java
@@ -0,0 +1,74 @@
+package com.gdsc.blog.article.service;
+
+import com.gdsc.blog.article.dto.UpdateDto;
+import com.gdsc.blog.article.entity.Article;
+import com.gdsc.blog.article.repository.ArticleRepository;
+import com.gdsc.blog.user.entity.User;
+import com.gdsc.blog.user.service.UserService;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@RequiredArgsConstructor
+@Service
+@Slf4j
+public class ArticleService {
+
+ private final ArticleRepository articleRepository;
+
+ public Article create(Article article, User user){
+ article.setCreateDate(LocalDateTime.now());
+ article.setUser(user);
+ return articleRepository.save(article);
+ }
+
+ public Article getArticle(Long id){
+ List Allarticle = articleRepository.findAll();
+
+ for(Article article: Allarticle){
+ if(article.getIdx() == id){
+ return article;
+ }
+ }
+ throw new RuntimeException("No article");
+ }
+
+ public List myAllArticle(User user){
+ return user.getArticleList();
+ }
+
+ public List getAllAriticle(){
+ return articleRepository.findAll();
+ }
+
+ public Article updateArticle(Long idx, UpdateDto newarticle, User user){
+ List Allarticle = articleRepository.findAll();
+
+ for(Article article: Allarticle){
+ if(article.getIdx() == idx){
+ article.setSubject(newarticle.getSubject());
+ article.setContent(newarticle.getContent());
+ return articleRepository.save(article);
+ }
+ }
+ throw new RuntimeException("No article");
+ }
+
+ public void deleteArticle(Long id, User user){
+ // find article by id
+ Article article = articleRepository.findById(id)
+ .orElseThrow(() -> new RuntimeException("Article not found"));
+
+ // check if the logged-in user is the owner of the article
+ if (!article.getUser().getIdx().equals(user.getIdx())) {
+ throw new RuntimeException("Permission denied");
+ }
+
+ // delete the article
+ articleRepository.delete(article);
+ }
+}
diff --git a/src/main/java/com/gdsc/blog/configuration/SecurityConfig.java b/src/main/java/com/gdsc/blog/configuration/SecurityConfig.java
index d194f30..9acd9ba 100644
--- a/src/main/java/com/gdsc/blog/configuration/SecurityConfig.java
+++ b/src/main/java/com/gdsc/blog/configuration/SecurityConfig.java
@@ -31,10 +31,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
"/v3/api-docs/**", "/api/user/signin", "/api/user/signup")
.permitAll().anyRequest().authenticated();
- http.csrf().disable();
+ http.csrf(csrf->csrf.disable());
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
-
return http.build();
}
}
diff --git a/src/main/java/com/gdsc/blog/security/jwt/JwtTokenFilter.java b/src/main/java/com/gdsc/blog/security/jwt/JwtTokenFilter.java
index 31e0c3d..e82448a 100644
--- a/src/main/java/com/gdsc/blog/security/jwt/JwtTokenFilter.java
+++ b/src/main/java/com/gdsc/blog/security/jwt/JwtTokenFilter.java
@@ -4,6 +4,7 @@
import java.io.IOException;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -16,6 +17,7 @@
// We should use OncePerRequestFilter since we are doing a database call, there is no point in doing
// this more than once
+@Slf4j
public class JwtTokenFilter extends OncePerRequestFilter {
private JwtTokenProvider jwtTokenProvider;
@@ -25,23 +27,29 @@ public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
}
@Override
+
protected void doFilterInternal(HttpServletRequest httpServletRequest,
- HttpServletResponse httpServletResponse, FilterChain filterChain)
- throws ServletException, IOException {
+ HttpServletResponse httpServletResponse, FilterChain filterChain)
+ throws ServletException, IOException {
+ logger.info("doFilterInternal 시작");
String token = jwtTokenProvider.resolveToken(httpServletRequest);
try {
+ logger.info("토큰 확인: " + token);
if (token != null && jwtTokenProvider.validateToken(token)) {
+ logger.info("토큰 검증 통과");
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (Exception ex) {
- // this is very important, since it guarantees the user is not authenticated at all
+ logger.error("예외 발생: " + ex.getMessage());
SecurityContextHolder.clearContext();
httpServletResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
+ logger.info("sendError 호출 후");
return;
}
-
+ logger.info("filterChain.doFilter 호출 전");
filterChain.doFilter(httpServletRequest, httpServletResponse);
+ logger.info("filterChain.doFilter 호출 후");
}
}
diff --git a/src/main/java/com/gdsc/blog/user/Member.java b/src/main/java/com/gdsc/blog/user/Member.java
deleted file mode 100644
index 17c4d64..0000000
--- a/src/main/java/com/gdsc/blog/user/Member.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.gdsc.blog.user;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import lombok.Getter;
-import lombok.Setter;
-
-@Entity
-@Getter
-@Setter
-public class Member {
- @Id
- private String ID;
- private String password;
- private String phone;
- @Column(unique = true)
- private String email;
-}
diff --git a/src/main/java/com/gdsc/blog/user/MemberController.java b/src/main/java/com/gdsc/blog/user/MemberController.java
deleted file mode 100644
index 7a878c2..0000000
--- a/src/main/java/com/gdsc/blog/user/MemberController.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.gdsc.blog.user;
-
-import com.gdsc.blog.JwtTokenProvider;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.*;
-
-@RequestMapping("/user")
-@Controller
-public class MemberController {
-
- private MemberService memberService;
- private JwtTokenProvider tokenProvider;
- public MemberController(MemberService memberService, JwtTokenProvider tokenProvider) {
- this.memberService = memberService;
- this.tokenProvider = tokenProvider;
- }
-
- @GetMapping("/login_ok")
- @ResponseBody
- public String login_ok(){
- return "로그인 성공";
- }
- @PostMapping("/login")
- @ResponseBody
- public String login(@RequestBody Member member){
- memberService.login(member.getID(), member.getPassword());
- return "redirect:/user/login_ok";
- }
- @PostMapping("/register")
- @ResponseBody
- public String register(@RequestBody Member member){
- ResponseEntity.ok(memberService.register(member));
- return "redirect:/user/login";
- }
-}
diff --git a/src/main/java/com/gdsc/blog/user/MemberRepository.java b/src/main/java/com/gdsc/blog/user/MemberRepository.java
deleted file mode 100644
index 6d0e558..0000000
--- a/src/main/java/com/gdsc/blog/user/MemberRepository.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.gdsc.blog.user;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface MemberRepository extends JpaRepository {
-}
diff --git a/src/main/java/com/gdsc/blog/user/MemberService.java b/src/main/java/com/gdsc/blog/user/MemberService.java
deleted file mode 100644
index 55c00a2..0000000
--- a/src/main/java/com/gdsc/blog/user/MemberService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.gdsc.blog.user;
-
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
-
-import java.util.Optional;
-
-@Service
-public class MemberService {
- private final MemberRepository memberRepository;
- private final PasswordEncoder passwordEncoder; //비밀번호 암호화
-
-
- public MemberService(MemberRepository memberRepository, PasswordEncoder passwordEncoder) {
- this.memberRepository = memberRepository;
- this.passwordEncoder = passwordEncoder;
- }
-
- public Member register(Member member){
- member.setID(member.getID());
- member.setPhone(member.getPhone());
- member.setEmail(member.getEmail());
- member.setPassword(passwordEncoder.encode(member.getPassword()));
- this.memberRepository.save(member);
- return member;
- }
- public Member login(String ID, String pwd){
- Optional member = memberRepository.findById(ID);
- if(member != null && passwordEncoder.matches(pwd, member.get().getPassword())){
- return member.get();
- }
- else
- return null;
- }
-}
diff --git a/src/main/java/com/gdsc/blog/user/controller/UserController.java b/src/main/java/com/gdsc/blog/user/controller/UserController.java
index 463a5d9..bf29c7a 100644
--- a/src/main/java/com/gdsc/blog/user/controller/UserController.java
+++ b/src/main/java/com/gdsc/blog/user/controller/UserController.java
@@ -1,7 +1,5 @@
package com.gdsc.blog.user.controller;
-import java.util.HashSet;
-import java.util.Set;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -18,7 +16,6 @@
import com.gdsc.blog.user.dto.SignUpDto;
import com.gdsc.blog.user.dto.Token;
import com.gdsc.blog.user.entity.User;
-import com.gdsc.blog.user.entity.UserRole;
@Slf4j
@Tag(name = "User", description = "User API")
@@ -49,13 +46,12 @@ public Token signin(@RequestBody SignInDto signInDto) {
Token token = Token.builder()
.token(userService.singin(signInDto.getEmail(), signInDto.getPassword())).build();
return token;
-
}
@GetMapping("/getUser/{email}")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public User getUser(@PathVariable("email") String email) {
- return userService.getUser(email);
+ return userService.getUserByEmail(email);
}
@GetMapping("/whoisme")
diff --git a/src/main/java/com/gdsc/blog/user/entity/User.java b/src/main/java/com/gdsc/blog/user/entity/User.java
index 28cddab..df6e8e1 100644
--- a/src/main/java/com/gdsc/blog/user/entity/User.java
+++ b/src/main/java/com/gdsc/blog/user/entity/User.java
@@ -4,19 +4,14 @@
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonManagedReference;
+import com.gdsc.blog.article.entity.Article;
+import jakarta.persistence.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
-import jakarta.persistence.Column;
-import jakarta.persistence.ElementCollection;
-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.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -27,7 +22,7 @@
@Builder
@AllArgsConstructor
@NoArgsConstructor
-@Table(name = "users")
+@Table(name = "users") //데이터 베이스에 존재하는 user랑 안겹치게?
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -43,4 +38,7 @@ public class User {
@ElementCollection(fetch = FetchType.EAGER)
List roles;
+ @JsonManagedReference
+ @OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE)
+ private List articleList;
}
diff --git a/src/main/java/com/gdsc/blog/user/service/UserService.java b/src/main/java/com/gdsc/blog/user/service/UserService.java
index 3160448..6fb9f61 100644
--- a/src/main/java/com/gdsc/blog/user/service/UserService.java
+++ b/src/main/java/com/gdsc/blog/user/service/UserService.java
@@ -1,12 +1,8 @@
package com.gdsc.blog.user.service;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.AuthenticationManager;
+
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.gdsc.blog.security.jwt.JwtTokenProvider;
@@ -57,8 +53,12 @@ public User signup(User user) {
return userRepository.save(user);
}
- public User getUser(String username) {
- return userRepository.findByEmail(username).get();
+ public User getUserByEmail(String useremail) {
+ return userRepository.findByEmail(useremail).get();
+ }
+
+ public User getUserByName(String username){
+ return userRepository.findByUsername(username).get();
}
public User whoami(HttpServletRequest req) {
@@ -67,5 +67,30 @@ public User whoami(HttpServletRequest req) {
.findByUsername(jwtTokenProvider.getUsername(jwtTokenProvider.resolveToken(req)))
.get();
}
-
+ /////////////////////////admin 유저 생성/////////////////
+// @EventListener
+// public void createAdminAccount(ApplicationReadyEvent event) {
+// // 관리자 계정 정보
+// String adminEmail = "admin";
+// String adminPassword = "admin";
+// String adminUsername = "admin";
+//
+// // 이미 관리자 계정이 존재하는지 확인
+// if (userRepository.existsByEmail(adminEmail)) {
+// return; // 이미 관리자 계정이 존재하면 생성하지 않음
+// }
+//
+// // 관리자 계정 생성
+// User adminUser = new User();
+// adminUser.setEmail(adminEmail);
+// adminUser.setPassword(passwordEncoder.encode(adminPassword));
+// adminUser.setUsername(adminUsername);
+// // admin 역할 부여
+// if (adminUser.getRoles() == null) {
+// List set = new ArrayList();
+// set.add(UserRole.ROLE_ADMIN);
+// adminUser.setRoles(set);
+// }
+// userRepository.save(adminUser);
+// }
}
diff --git a/src/test/java/com/gdsc/blog/BlogApplicationTests.java b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
index 4c1d341..fb65d4a 100644
--- a/src/test/java/com/gdsc/blog/BlogApplicationTests.java
+++ b/src/test/java/com/gdsc/blog/BlogApplicationTests.java
@@ -1,7 +1,7 @@
package com.gdsc.blog;
-import com.gdsc.blog.user.Member;
-import com.gdsc.blog.user.MemberRepository;
+import com.gdsc.blog.user.entity.User;
+import com.gdsc.blog.user.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@@ -15,20 +15,10 @@
@Profile("test")
class BlogApplicationTests {
@Autowired
- MemberRepository userRepository;
+ UserRepository userRepository;
@Test
void testJoin() { //회원가입 테스트
- Member user1 = new Member();
- user1.setID("cj8556");
- user1.setPassword("test1234");
- this.userRepository.save(user1);
- Optional oq = this.userRepository.findById("cj8556");
- if(oq.isPresent()) {
- Member q = oq.get();
- assertEquals("cj8556", q.getID());
- assertEquals("test1234",q.getPassword());
- }
}
@Test