signup with session

This commit is contained in:
jinho jeong
2022-04-22 17:05:04 +09:00
parent 0890444034
commit 3b6963344d
15 changed files with 290 additions and 18 deletions

View File

@@ -22,9 +22,12 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.session:spring-session-data-redis'
implementation 'org.springframework.session:spring-session-core'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'

View File

@@ -2,10 +2,13 @@ package com.example.oneul.DTO;
import com.example.oneul.model.UserEntity;
import lombok.Getter;
@Getter
public class LoginDTO {
private String username;
private String password;
public LoginDTO(String username, String password){
this.username = username;
this.password = password;

View File

@@ -0,0 +1,39 @@
package com.example.oneul.DTO;
import com.example.oneul.model.UserEntity;
import lombok.Getter;
@Getter
public class SignUpDTO {
private String username;
private String password1;
private String password2;
public void setUsername(String username ){
this.username = username;
}
public void setPassword1(String password1){
this.password1 = password1;
}
public void setPassword2(String password2){
this.password2 = password2;
}
public SignUpDTO() {}
public SignUpDTO(String username, String password1, String password2){
this.username = username;
this.password1 = password1;
this.password2 = password2;
}
public UserEntity toEntity(){
return UserEntity.builder()
.username(this.username)
.password(this.password1)
.build();
}
}

View File

@@ -2,10 +2,14 @@ package com.example.oneul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@SpringBootApplication
@EnableJpaAuditing
@EnableRedisHttpSession
public class OneulApplication {
public static void main(String[] args) {
SpringApplication.run(OneulApplication.class, args);
}

View File

@@ -0,0 +1,37 @@
package com.example.oneul.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String hostName;
@Value("${spring.redis.port}")
private int port;
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(hostName);
redisStandaloneConfiguration.setPort(port);
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration);
return lettuceConnectionFactory;
}
}

View File

@@ -0,0 +1,26 @@
package com.example.oneul.config;
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().disable()
.csrf().disable()
.formLogin().disable()
.headers().frameOptions().disable();
}
}

View File

@@ -0,0 +1,34 @@
package com.example.oneul.controller;
import javax.servlet.http.HttpSession;
import com.example.oneul.DTO.SignUpDTO;
import com.example.oneul.model.UserEntity;
import com.example.oneul.service.command.UserCommandService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/user")
public class UserController {
private final UserCommandService userCommandService;
private final Logger log = LoggerFactory.getLogger(UserController.class);
public UserController(UserCommandService userCommandService){
this.userCommandService = userCommandService;
}
@RequestMapping(value="/", method=RequestMethod.POST)
public UserEntity signUp(@RequestBody SignUpDTO signUpDTO, HttpSession httpSession) {
UserEntity user = userCommandService.signUp(signUpDTO.toEntity(), httpSession);
return user;
}
}

View File

@@ -1,19 +1,23 @@
package com.example.oneul.model;
import java.time.LocalDateTime;
import java.util.Objects;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Post {
@Id @GeneratedValue
private Long id;
@@ -66,6 +70,23 @@ public class Post {
this.writer = writer;
}
@Override
public boolean equals(Object object){
if(this == object) {
return true;
}
if(object == null || getClass() != object.getClass()) {
return false;
}
Post that = (Post) object;
return this.id == that.id;
}
@Override
public int hashCode() {
return Objects.hash(this.id);
}
@Override
public String toString(){
return "Post["

View File

@@ -1,19 +1,24 @@
package com.example.oneul.model;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Entity
public class UserEntity {
@EntityListeners(AuditingEntityListener.class)
public class UserEntity implements Serializable {
@Id @GeneratedValue
private Long id;
@Column(nullable = false, unique = true)
@@ -71,6 +76,23 @@ public class UserEntity {
this.createdAt = user.getCreatedAt();
}
@Override
public boolean equals(Object object){
if(this == object) {
return true;
}
if(object == null || getClass() != object.getClass()) {
return false;
}
UserEntity that = (UserEntity) object;
return this.id == that.id;
}
@Override
public int hashCode() {
return Objects.hash(this.id);
}
@Override
public String toString(){
return "userEntity["

View File

@@ -4,9 +4,11 @@ import java.util.Optional;
import com.example.oneul.model.UserEntity;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@RedisHash
@Repository
public interface UserCommandRepository extends CrudRepository<UserEntity, Long> {
Optional<UserEntity> findByUsername(String username);

View File

@@ -1,10 +1,12 @@
package com.example.oneul.service.command;
import javax.servlet.http.HttpSession;
import com.example.oneul.model.UserEntity;
import org.springframework.stereotype.Service;
@Service
public interface UserCommandService {
UserEntity signUp(UserEntity userEntity);
UserEntity signUp(UserEntity userEntity, HttpSession httpSession);
}

View File

@@ -1,6 +1,7 @@
package com.example.oneul.service.command;
import com.example.oneul.exception.UserAlreadyExistException;
import javax.servlet.http.HttpSession;
import com.example.oneul.model.UserEntity;
import com.example.oneul.repository.UserCommandRepository;
@@ -25,15 +26,15 @@ public class UserCommandServiceImpl implements UserCommandService {
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public UserEntity signUp(UserEntity userEntity){
userCommandRepository.findByUsername(userEntity.getUsername()).ifPresent(user -> {
log.debug(user.getUsername() + " is present");
throw new UserAlreadyExistException(userEntity.getUsername() + " is already exist.");
});
public UserEntity signUp(UserEntity userEntity, HttpSession httpSession){
// ANCHOR: 이게 맞나..?
userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword()));
UserEntity user = new UserEntity(userEntity);
return userCommandRepository.save(user);
UserEntity user = userCommandRepository.save(new UserEntity(userEntity));
httpSession.setAttribute("user",user);
log.info("session id: " + httpSession.getId());
log.info("session value: " + httpSession.getAttribute("user"));
return user;
}
}

View File

@@ -11,6 +11,14 @@ spring:
url: jdbc:h2:tcp://localhost/~/test
driver-class-name: org.h2.Driver
username: "sa"
redis:
host: 127.0.0.1
port: 6379
server:
servlet:
session:
timeout: 60
logging:
level:

View File

@@ -0,0 +1,62 @@
package com.example.oneul.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.HashMap;
import java.util.Map;
import com.example.oneul.service.command.UserCommandService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
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.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.filter.CharacterEncodingFilter;
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
private MockMvc mvc;
@Autowired
private UserCommandService userCommandService;
private MockHttpSession httpSession = new MockHttpSession();
@BeforeEach
public void setUp(){
mvc = MockMvcBuilders.standaloneSetup(new UserController(userCommandService))
.addFilters(new CharacterEncodingFilter("UTF-8", true))
.build();
}
@Test
@DisplayName("signUp test")
public void signUpTest() throws Exception {
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("username", "zzzinho");
requestBody.put("password1", "password");
requestBody.put("password2", "password");
String json = new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(requestBody);
final ResultActions actions = mvc.perform(
post("/user/")
.contentType(MediaType.APPLICATION_JSON)
.session(httpSession)
.accept(MediaType.APPLICATION_JSON)
.characterEncoding("UTF-8")
.content(json)
);
actions.andExpectAll(status().isOk());
}
}

View File

@@ -1,5 +1,7 @@
package com.example.oneul.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.example.oneul.DTO.LoginDTO;
import com.example.oneul.model.UserEntity;
import com.example.oneul.service.command.UserCommandService;
@@ -9,18 +11,24 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.crypto.password.PasswordEncoder;
@Transactional
@SpringBootTest
@ExtendWith(MockitoExtension.class)
public class UserCommandServiceTest {
@Autowired
private UserCommandService userCommandService;
@Autowired
private PasswordEncoder passwordEncoder;
protected MockHttpSession httpSession;
@Test
public void signUpTest(){
httpSession = new MockHttpSession();
LoginDTO loginDTO = new LoginDTO("zzzinho", "password");
UserEntity user = userCommandService.signUp(loginDTO.toEntity());
UserEntity user = userCommandService.signUp(loginDTO.toEntity(), httpSession);
assertEquals(loginDTO.getUsername(), user.getUsername());
assertEquals(true, passwordEncoder.matches(loginDTO.getPassword(), user.getPassword()));
}
}