Implement Auth

This commit is contained in:
hou27
2022-06-10 22:17:55 +09:00
parent c51cf8b525
commit f307710223
14 changed files with 191 additions and 87 deletions

View File

@@ -0,0 +1,49 @@
package demo.api.auth;
import demo.api.jwt.dtos.TokenDto;
import demo.api.user.domain.User;
import demo.api.user.dtos.UserSignInRequest;
import demo.api.user.dtos.UserSignUpRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthService authService;
@GetMapping("/signUp")
public String signUp() {
return "user/signUp";
}
@PostMapping("/signUp")
public String signUp(@Validated UserSignUpRequest signUpReq) throws Exception {
User user = authService.signUp(signUpReq);
if(user.getEmail() != "") {
return "redirect:/user/signIn";
}
return "redirect:/user/signUp";
}
@GetMapping("/signIn")
public String signIn(@RequestParam(value = "fail", required = false) String flag, Model model) {
model.addAttribute("failed", flag != null);
return "user/signIn";
}
@PostMapping
public TokenDto signIn(@Validated UserSignInRequest signInReq) {
return authService.signIn(signInReq);
}
}

View File

@@ -0,0 +1,22 @@
package demo.api.auth;
import demo.api.jwt.dtos.TokenDto;
import demo.api.user.domain.User;
import demo.api.user.dtos.UserSignInRequest;
import demo.api.user.dtos.UserSignUpRequest;
public interface AuthService {
/**
* 유저의 정보로 회원가입
* @param signUpReq 가입할 유저의 정보 Dto
* @return 가입된 유저 정보
*/
User signUp(UserSignUpRequest signUpReq) throws Exception;
/**
* 유저 정보로 로그인
* @param signInReq 유저의 이메일과 비밀번호
* @return json web token
*/
TokenDto signIn(UserSignInRequest signInReq);
}

View File

@@ -0,0 +1,67 @@
package demo.api.auth;
import demo.api.exception.CustomException;
import demo.api.jwt.JwtTokenProvider;
import demo.api.jwt.dtos.TokenDto;
import demo.api.user.domain.User;
import demo.api.user.dtos.UserSignInRequest;
import demo.api.user.dtos.UserSignUpRequest;
import demo.api.user.repository.UserRepository;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {
private final UserRepository userRepository;
private final PasswordEncoder bCryptPasswordEncoder;
private final JwtTokenProvider jwtTokenProvider;
private final AuthenticationManager authenticationManager;
@Override
@Transactional
public User signUp(UserSignUpRequest signUpReq) throws Exception {
System.out.println("signUpReq = " + signUpReq.toString());
if(this.isEmailExist(signUpReq.getEmail())) {
throw new Exception("Your Mail already Exist.");
}
User newUser = signUpReq.toUserEntity();
newUser.hashPassword(bCryptPasswordEncoder);
return userRepository.save(newUser);
}
@Override
public TokenDto signIn(UserSignInRequest signInReq) {
try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
signInReq.getEmail(),
signInReq.getPassword()
)
);
return new TokenDto(jwtTokenProvider.generateToken(authentication));
} catch (AuthenticationException e) {
throw new CustomException("Invalid credentials supplied", HttpStatus.UNPROCESSABLE_ENTITY);
}
}
/**
* 이메일 중복 여부를 확인
*
* @param email
* @return true | false
*/
private boolean isEmailExist(String email) {
Optional<User> byEmail = userRepository.findByEmail(email);
return !byEmail.isEmpty();
}
}

View File

@@ -22,10 +22,6 @@ public class SecurityConfig {
private final JwtAccessDeniedHandler jwtAccessDeniedHandler; private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
// @Bean
// public UserDetailsService userDetailsService() {
// return new UserDetailsServiceImpl();
// }
@Bean @Bean
public BCryptPasswordEncoder passwordEncoder() { public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();
@@ -48,9 +44,9 @@ public class SecurityConfig {
.authorizeRequests() .authorizeRequests()
.antMatchers( .antMatchers(
"/", "/",
"/user/signUp", "/auth/signUp",
"/user/userList", "/user/userList",
"/user/signIn*", "/auth/signIn*",
"/favicon.ico" "/favicon.ico"
).permitAll() ).permitAll()
.anyRequest().authenticated(); .anyRequest().authenticated();

View File

@@ -15,7 +15,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Component @Service
public class UserDetailsServiceImpl implements UserDetailsService { public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;

View File

@@ -0,0 +1,8 @@
package demo.api.jwt.dtos;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class TokenDto {
private String access_token;
}

View File

@@ -24,25 +24,6 @@ import org.springframework.web.bind.annotation.RequestParam;
public class UserController { public class UserController {
private final UserService userService; private final UserService userService;
@GetMapping("/signUp")
public String signUp() {
return "user/signUp";
}
@PostMapping("/signUp")
public String signUp(@Validated UserSignUpRequest signUpReq) throws Exception {
User user = userService.signUp(signUpReq);
return "redirect:/user/signIn";
}
@GetMapping("/signIn")
public String signIn(@RequestParam(value = "fail", required = false) String flag, Model model) {
model.addAttribute("failed", flag != null);
return "user/signIn";
}
@GetMapping("/profile") @GetMapping("/profile")
public String profile(Model model, @AuthenticationPrincipal UserDetails userDetails) { public String profile(Model model, @AuthenticationPrincipal UserDetails userDetails) {
if (userDetails != null) { if (userDetails != null) {

View File

@@ -6,13 +6,6 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
public interface UserService { public interface UserService {
/**
* 유저의 정보로 회원가입
* @param signUpReq 가입할 유저의 정보 Dto
* @return 가입된 유저 정보
*/
User signUp(UserSignUpRequest signUpReq) throws Exception;
/** /**
* 모든 유저 리스트를 반환 * 모든 유저 리스트를 반환
* @return 유저 리스트 * @return 유저 리스트

View File

@@ -1,32 +1,16 @@
package demo.api.user; package demo.api.user;
import demo.api.user.domain.User; import demo.api.user.domain.User;
import demo.api.user.dtos.UserSignUpRequest;
import demo.api.user.repository.UserRepository; import demo.api.user.repository.UserRepository;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@Transactional
public class UserServiceImpl implements UserService { public class UserServiceImpl implements UserService {
private final UserRepository userRepository; private final UserRepository userRepository;
private final PasswordEncoder bCryptPasswordEncoder;
@Override
public User signUp(UserSignUpRequest signUpReq) throws Exception {
System.out.println("signUpReq = " + signUpReq.toString());
if(this.isEmailExist(signUpReq.getEmail())) {
throw new Exception("Your Mail already Exist.");
}
User newUser = signUpReq.toUserEntity();
newUser.hashPassword(bCryptPasswordEncoder);
return userRepository.save(newUser);
}
@Override @Override
public List<User> findAll() { public List<User> findAll() {
@@ -42,15 +26,4 @@ public class UserServiceImpl implements UserService {
public User updateUser(User user, String newInfo) { public User updateUser(User user, String newInfo) {
return null; return null;
} }
/**
* 이메일 중복 여부를 확인
*
* @param email
* @return true | false
*/
private boolean isEmailExist(String email) {
Optional<User> byEmail = userRepository.findByEmail(email);
return !byEmail.isEmpty();
}
} }

View File

@@ -0,0 +1,26 @@
package demo.api.user.dtos;
import demo.api.user.domain.User;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@ToString
public class UserSignInRequest {
@NotEmpty(message = "Please enter your Email")
@Email
private String email;
@NotEmpty(message = "Please enter your Password")
private String password;
@Builder
public UserSignInRequest(String email, String password) {
this.email = email;
this.password = password;
}
}

View File

@@ -5,7 +5,7 @@ import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
// @Repository @Repository
public interface UserRepository extends JpaRepository<User, Long> { public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email); Optional<User> findByEmail(String email);

View File

@@ -10,7 +10,7 @@
<h2>로그인</h2> <h2>로그인</h2>
</div> </div>
<h3 th:if="${failed}">Fail to login</h3> <h3 th:if="${failed}">Fail to login</h3>
<form action="/user/signInProc" method="post"> <form action="/auth/signIn" method="post">
<div class="form-group"> <div class="form-group">
<label for="email">Email</label> <label for="email">Email</label>
<input type="email" id="email" name="email" placeholder="Enter your email"> <input type="email" id="email" name="email" placeholder="Enter your email">

View File

@@ -5,7 +5,7 @@
<div> <div>
<h2>회원가입</h2> <h2>회원가입</h2>
</div> </div>
<form action="/user/signUp" method="post"> <form action="/auth/signUp" method="post">
<div class="form-group"> <div class="form-group">
<label for="email">Email</label> <label for="email">Email</label>
<input type="text" id="email" name="email" placeholder="Enter your email"> <input type="text" id="email" name="email" placeholder="Enter your email">

View File

@@ -3,24 +3,17 @@ package demo.api.user.service;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import demo.api.AppConfig; import demo.api.auth.AuthService;
import demo.api.user.UserService; import demo.api.user.UserService;
import demo.api.user.UserServiceImpl;
import demo.api.user.domain.User; import demo.api.user.domain.User;
import demo.api.user.dtos.UserSignUpRequest; import demo.api.user.dtos.UserSignUpRequest;
import demo.api.user.repository.UserRepository; import demo.api.user.repository.UserRepository;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -31,17 +24,13 @@ class UserServiceTest {
private static final String EMAIL = "test@email.com"; private static final String EMAIL = "test@email.com";
private static final String PASSWORD = "12345"; private static final String PASSWORD = "12345";
private static final String NAME = "김정호"; private static final String NAME = "김정호";
private UserService userService;
@Autowired
private UserRepository userRepository;
@Autowired @Autowired
private PasswordEncoder bCryptPasswordEncoder; private PasswordEncoder bCryptPasswordEncoder;
@Autowired
@BeforeEach private UserService userService;
public void beforeEach() { @Autowired
AppConfig appConfig = new AppConfig(userRepository, bCryptPasswordEncoder); private AuthService authService;
userService = appConfig.userService();
}
@Test @Test
@DisplayName("유저 회원가입") @DisplayName("유저 회원가입")
@@ -51,7 +40,7 @@ class UserServiceTest {
System.out.println("user = " + user.toString()); System.out.println("user = " + user.toString());
// when // when
User newUser = userService.signUp(user); User newUser = authService.signUp(user);
// then // then
System.out.println("newUser = " + newUser.toString()); System.out.println("newUser = " + newUser.toString());
@@ -65,7 +54,7 @@ class UserServiceTest {
UserSignUpRequest user = createSignUpRequest(); UserSignUpRequest user = createSignUpRequest();
// when // when
User newUser = userService.signUp(user); User newUser = authService.signUp(user);
// then // then
System.out.println("newUser pw = " + newUser.getPassword()); System.out.println("newUser pw = " + newUser.getPassword());
@@ -78,10 +67,10 @@ class UserServiceTest {
// given // given
UserSignUpRequest user = createSignUpRequest(); UserSignUpRequest user = createSignUpRequest();
System.out.println("user = " + user.toString()); System.out.println("user = " + user.toString());
User newUser = userService.signUp(user); User newUser = authService.signUp(user);
// when // when
Boolean flag = newUser.checkPassword(PASSWORD, bCryptPasswordEncoder); boolean flag = newUser.checkPassword(PASSWORD, bCryptPasswordEncoder);
System.out.println("flag = " + flag); System.out.println("flag = " + flag);
// then // then
@@ -94,7 +83,7 @@ class UserServiceTest {
List<User> prevUserList = userService.findAll(); List<User> prevUserList = userService.findAll();
int prevLen = prevUserList.size(); int prevLen = prevUserList.size();
UserSignUpRequest user1 = createSignUpRequest(); UserSignUpRequest user1 = createSignUpRequest();
userService.signUp(user1); authService.signUp(user1);
// when // when
List<User> userList = userService.findAll(); List<User> userList = userService.findAll();
@@ -108,7 +97,7 @@ class UserServiceTest {
void findByEmail() throws Exception { void findByEmail() throws Exception {
// given // given
UserSignUpRequest user1 = createSignUpRequest(); UserSignUpRequest user1 = createSignUpRequest();
userService.signUp(user1); authService.signUp(user1);
// when // when
Optional<User> byEmail = userService.findByEmail(EMAIL); Optional<User> byEmail = userService.findByEmail(EMAIL);