This repository has been archived by the owner on Aug 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 회원가입 기능을 통해 Careers를 로그인 한 사용자들만 이용할 수 있도록 한다. - 이름, 이메일, 비밀번호 모두를 입력 받는다.(Null 체크) - 이메일은 이메일 형식에 맞게 작성해야 한다. - 비밀번호는 문자, 숫자, 특수문자로 구성되어야 한다. - 비밀번호는 암호화하여 DB에 저장한다.(sha-256) - 중복된 이메일인지 체크하여 중복가입을 제한한다. #3
- Loading branch information
1 parent
c29bca5
commit 7d57c84
Showing
10 changed files
with
285 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
create table Curator( | ||
email varchar(64) not null primary key, | ||
username varchar(64) not null, | ||
password varchar(64) not null, | ||
salt varchar(64) not null | ||
); |
40 changes: 40 additions & 0 deletions
40
src/main/java/com/dev/careers/controller/CuratorController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.dev.careers.controller; | ||
|
||
import com.dev.careers.model.Curator; | ||
import com.dev.careers.service.CuratorService; | ||
import org.springframework.validation.BindingResult; | ||
import org.springframework.validation.ObjectError; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.ModelAttribute; | ||
import org.springframework.web.bind.annotation.PutMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import javax.validation.Valid; | ||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
@RestController | ||
public class CuratorController { | ||
|
||
private final CuratorService curatorService; | ||
|
||
public CuratorController(CuratorService curatorService) { | ||
this.curatorService = curatorService; | ||
} | ||
|
||
@PutMapping("/curators/join") | ||
public String putMember(@Valid @ModelAttribute Curator curator, BindingResult bindingResult) throws Exception { | ||
if (bindingResult.hasErrors()){ | ||
Optional<ObjectError> objectError = bindingResult.getAllErrors().stream().findFirst(); | ||
if (objectError.isPresent()){ | ||
return objectError.get().getDefaultMessage(); | ||
} | ||
} | ||
return curatorService.join(curator); | ||
} | ||
|
||
@GetMapping("/curators/all") | ||
public List<Curator> getMembers(){ | ||
return curatorService.getMembers(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.dev.careers.mapper; | ||
|
||
import com.dev.careers.model.Curator; | ||
import org.apache.ibatis.annotations.Mapper; | ||
import org.apache.ibatis.annotations.Param; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.List; | ||
|
||
@Repository | ||
@Mapper | ||
public interface CuratorMapper { | ||
|
||
Integer insertCurator( | ||
@Param("email") String email, | ||
@Param("name") String name, | ||
@Param("password") String password, | ||
@Param("salt") String salt); | ||
|
||
List<Curator> getCurators(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.dev.careers.model; | ||
|
||
import lombok.Data; | ||
import lombok.NonNull; | ||
import org.springframework.lang.Nullable; | ||
|
||
import javax.validation.constraints.Email; | ||
import javax.validation.constraints.Pattern; | ||
|
||
|
||
@Data | ||
public class Curator { | ||
@NonNull | ||
@Email(message = "Email Format Violation") | ||
private String email; | ||
@NonNull | ||
private String name; | ||
@NonNull | ||
//최소 8자리에 숫자, 문자, 특수문자 각각 1개 이상 포함 | ||
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,}$", | ||
message = "Password Format Violation") | ||
private String password; | ||
@Nullable | ||
private String salt; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.dev.careers.service; | ||
|
||
import com.dev.careers.mapper.CuratorMapper; | ||
import com.dev.careers.model.Curator; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.SecureRandom; | ||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
@Service | ||
public class CuratorService { | ||
private final CuratorMapper curatorMapper; | ||
private final int SALT_SIZE = 16; | ||
|
||
public CuratorService(CuratorMapper curatorMapper) { | ||
this.curatorMapper = curatorMapper; | ||
} | ||
|
||
public String join(Curator curator) throws NoSuchAlgorithmException { | ||
//중복검증 | ||
Optional<Curator> memberOptional = getMembers() | ||
.stream() | ||
.filter(m -> m.getEmail().equals(curator.getEmail())) | ||
.findAny(); | ||
|
||
if (memberOptional.isPresent()) { | ||
return "Duplicated Email"; | ||
} else { | ||
String salt = makeSalt(); | ||
|
||
curatorMapper.insertCurator( | ||
curator.getEmail(), | ||
curator.getName(), | ||
hashing(curator.getPassword().getBytes(), salt), | ||
salt); | ||
|
||
return "Success"; | ||
} | ||
} | ||
|
||
private String makeSalt() { | ||
SecureRandom srd = new SecureRandom(); | ||
byte[] data = new byte[SALT_SIZE]; | ||
srd.nextBytes(data); | ||
|
||
return byteArrayToString(data); | ||
} | ||
|
||
//Salt와 키 스트레칭 방식으로 구현 | ||
private String hashing(byte[] password, String salt) throws NoSuchAlgorithmException { | ||
MessageDigest md = MessageDigest.getInstance("SHA-256"); | ||
|
||
StringBuffer buffer = new StringBuffer(); | ||
for (int i = 0; i < 10; i++) { | ||
buffer.append(byteArrayToString(password)); | ||
buffer.append(salt); | ||
md.update(buffer.toString().getBytes()); | ||
password = md.digest(); | ||
} | ||
return new String(password); | ||
} | ||
|
||
public String byteArrayToString(byte[] bytes) { | ||
StringBuilder builder = new StringBuilder(); | ||
for (byte data : bytes) { | ||
builder.append(String.format("%02X ", data)); | ||
} | ||
return builder.toString(); | ||
} | ||
|
||
public List<Curator> getMembers() { | ||
return curatorMapper.getCurators(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
spring.datasource.url=jdbc:mysql://localhost:3306/<디비이름>?useUnicode=true@characterEncoding=utf8&serverTimezone=Asia/Seoul | ||
spring.datasource.username=<유저이름> | ||
spring.datasource.password=<유저비밀번호> | ||
spring.datasource.url=jdbc:mysql://localhost:3306/Careers?useUnicode=true@characterEncoding=utf8&serverTimezone=Asia/Seoul | ||
#<유저이름> | ||
spring.datasource.username=junehee | ||
# <유저비밀번호> | ||
spring.datasource.password=wnsgml12 | ||
mybatis.type-aliases-package=com.dev.careers.model | ||
mybatis.mapper-locations=mybatis/*.xml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
<mapper namespace="com.dev.careers.mapper.CuratorMapper"> | ||
<select id="insertCurator" resultType="int"> | ||
INSERT INTO Curator VALUES(#{email}, #{name}, #{password}, #{salt}); | ||
</select> | ||
|
||
<select id="getCurators" resultType="Curator"> | ||
SELECT * from Curator; | ||
</select> | ||
</mapper> |
64 changes: 64 additions & 0 deletions
64
src/test/java/com/dev/careers/controller/CuratorControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.dev.careers.controller; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
|
||
@SpringBootTest | ||
@Transactional | ||
class CuratorControllerTest { | ||
|
||
@Autowired | ||
CuratorController curatorController; | ||
MockMvc mockMvc; | ||
|
||
@BeforeEach | ||
public void beforeEach(){ | ||
mockMvc = MockMvcBuilders.standaloneSetup(curatorController).build(); | ||
} | ||
|
||
@Test | ||
@DisplayName("정상적인 회원가입") | ||
public void joinCurator() throws Exception { | ||
mockMvc.perform(put("/curators/join") | ||
.param("email","test@google.com") | ||
.param("name", "홍길동") | ||
.param("password", "test123!@")) | ||
.andDo(print()) | ||
.andExpect(status().isOk()); | ||
} | ||
|
||
@Test | ||
@DisplayName("잘못된 이메일 형식 요청") | ||
public void violationEmail() throws Exception { | ||
mockMvc.perform(put("/curators/join") | ||
.param("email", "test123.com") | ||
.param("name", "홍길동") | ||
.param("password", "test123!@")) | ||
.andDo(print()) | ||
.andExpect(status().isOk()) | ||
.andExpect(content().string("Email Format Violation")); | ||
} | ||
|
||
@Test | ||
@DisplayName("잘못된 비밀번호 형식 요청") | ||
public void violationPassword() throws Exception { | ||
mockMvc.perform(put("/curators/join") | ||
.param("email", "test@google.com") | ||
.param("name", "홍길동") | ||
.param("password", "123")) | ||
.andDo(print()) | ||
.andExpect(status().isOk()) | ||
.andExpect(content().string("Password Format Violation")); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/test/java/com/dev/careers/service/CuratorServiceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package com.dev.careers.service; | ||
|
||
import com.dev.careers.model.Curator; | ||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.dao.DuplicateKeyException; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Transactional | ||
@SpringBootTest | ||
class CuratorServiceTest { | ||
|
||
@Autowired | ||
CuratorService curatorService; | ||
|
||
@Test | ||
@DisplayName("중복된 이메일 회원가입 요청") | ||
public void DupicatedEmail() throws Exception { | ||
Curator curator = new Curator( | ||
"test@google.com", | ||
"홍길동", | ||
"test123!@" | ||
); | ||
Assertions.assertThat(curatorService.join(curator)).isEqualTo("Success"); | ||
org.junit.jupiter.api.Assertions.assertThrows( | ||
DuplicateKeyException.class, | ||
()->curatorService.join(curator)); | ||
} | ||
} |