Implement login with session

This commit is contained in:
hou27
2022-05-29 03:02:29 +09:00
parent f613686c45
commit 9a7ea77820
17 changed files with 301 additions and 10 deletions

View File

@@ -1,11 +1,14 @@
package demo.api.config;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
@@ -14,7 +17,9 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
* @Configuration 애노테이션 대신 @EnableWebSecurity 애노테이션을 추가한다.
*/
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
/**
* PasswordEncoder를 Bean으로 등록
@@ -32,6 +37,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
// web.ignoring().antMatchers("/?/**");
// }
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
/**
* 인증 or 인가에 대한 설정
*/
@@ -39,9 +49,16 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin().disable()//loginPage("/user/signIn")
.formLogin()
.loginPage("/user/signIn")
.loginProcessingUrl("/user/signInProc")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/")
.failureUrl("/user/signIn?fail=true");
http
.authorizeRequests()
.antMatchers("/", "/user/signUp").permitAll()
.antMatchers("/", "/user/signUp", "/user/userList", "/user/signIn*").permitAll()
.anyRequest().authenticated();
}
}

View File

@@ -0,0 +1,35 @@
package demo.api.config;
import demo.api.user.domain.User;
import demo.api.user.exception.UserNotFoundException;
import demo.api.user.repository.UserRepository;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UserNotFoundException {
User user = userRepository.findByEmail(email)
.orElseThrow(() -> new UserNotFoundException());
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
return new org
.springframework
.security
.core
.userdetails
.User(user.getEmail(), user.getPassword(), grantedAuthorities);
}
}

View File

@@ -0,0 +1,12 @@
package demo.api.home;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}

View File

@@ -1,25 +1,71 @@
package demo.api.user;
import demo.api.user.domain.User;
import demo.api.user.dtos.UserSignInRequest;
import demo.api.user.dtos.UserSignUpRequest;
import demo.api.user.exception.UserNotFoundException;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
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.RestController;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* User 관련 HTTP 요청 처리
*/
@RestController
@Controller
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/signUp")
public String signUp() {
return "user/signUp";
}
@PostMapping("/signUp")
public User signUp(@Validated UserSignUpRequest signUpReq) throws Exception {
return userService.signUp(signUpReq);
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) {
if(flag == null || !flag.equals("true")) {
model.addAttribute("failed", false);
return "user/signIn";
}
else {
model.addAttribute("failed", true);
return "user/signIn";
}
}
@GetMapping("/profile")
public String profile(Model model, @AuthenticationPrincipal User user) {
User userDetail = userService.findByEmail(user.getEmail())
.orElseThrow(() -> new UserNotFoundException());
model.addAttribute("userDetail", userDetail);
return "user/profile";
}
@GetMapping("/user/userList")
public String showUserList(Model model) {
List<User> userList = userService.findAll();
model.addAttribute("userList", userList);
return "user/userList";
}
}

View File

@@ -1,6 +1,7 @@
package demo.api.user;
import demo.api.user.domain.User;
import demo.api.user.dtos.UserSignInRequest;
import demo.api.user.dtos.UserSignUpRequest;
import java.util.List;
import java.util.Optional;

View File

@@ -1,6 +1,7 @@
package demo.api.user;
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.List;

View File

@@ -1,8 +1,11 @@
package demo.api.user.domain;
import demo.api.common.domain.CoreEntity;
import demo.api.user.repository.UserRepository;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -23,11 +26,15 @@ public class User extends CoreEntity {
@Column(length = 10, nullable = false)
private String name;
// @Enumerated(EnumType.STRING)
// private UserRole role;
@Builder
public User(String email, String password, String name) {
public User(String email, String password, String name /*UserRole role*/) {
this.email = email;
this.password = password;
this.name = name;
// this.role = role;
}
// https://reflectoring.io/spring-security-password-handling/

View File

@@ -0,0 +1,8 @@
package demo.api.user.domain;
import lombok.Getter;
@Getter
public enum UserRole {
ROLE_USER // Spring Security의 role 네이밍 규칙 : ROLE_권한이름
}

View File

@@ -0,0 +1,20 @@
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;
}

View File

@@ -0,0 +1,8 @@
package demo.api.user.exception;
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException() {
super("Can't find User");
}
}