일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- spring 게시판 삭제
- 객체
- SQL 튜닝
- 친절한 SQL 튜닝
- 스프링시큐리티 로그아웃
- 객체지향
- 인텔리제이 Web 애플리케이션
- 이클립스 설치
- 예약어
- 오버라이딩
- java
- SpringSecurity 로그아웃
- 식별자
- 비교 연산자
- 오버로딩
- SQL튜닝
- 자바의정석
- 산술 연산자
- 반복문
- 함수
- @PreAuthorize("isAuthenticated()")
- 상속
- 배열
- 논리 연산자
- SpringSecurity 로그인
- 친절한 SQL
- SQL
- join
- StringBuffer
- 연산자
Archives
- Today
- Total
gi_dor
회원가입 - SpringSecurity , @Valid , MySQL , MyBatis 본문
SpringSecurity - SecurityConfig
@Configuration // 빈 설정
@EnableWebSecurity // 스프링 시큐리티 웹보안 활성화
@EnableMethodSecurity(prePostEnabled = true , securedEnabled = true)
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain (HttpSecurity http) throws Exception{
// csrf 공격을 방지하는 기술 비활성화
http.csrf(csrf -> csrf.disable());
http.authorizeHttpRequests(authorizeHttpRequest -> authorizeHttpRequest.requestMatchers("/**").permitAll());
// 폼기반 로그인을 활성화
// 사용자가 로그인 한다면 /user/login 경로로 이동하게되는데 로그인 성공시 ("/") 로 리다이렉트
http.formLogin(formLogin -> formLogin.loginPage("/user/login").defaultSuccessUrl("/"));
// 로그아웃
// HTTP 세션을 무효화해서 로그인 상태를 제거한다
http.logout(logout -> logout.logoutUrl("/user/logout").logoutSuccessUrl("/").invalidateHttpSession(true));
return http.build();
}
// 비밀번호 암호화
// salt 사용
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
http.formLogin(formLogin -> formLogin.loginPage("/user/login").defaultSuccessUrl("/"))
로그인 페이지를 "/user/login"으로 지정하며, 로그인 성공 시 기본적으로 홈 페이지("/")로 redirect .
http.logout(logout -> logout.logoutUrl("/user/logout").logoutSuccessUrl("/").invalidateHttpSession(true))
로그아웃을 활성화하고, "/user/logout" 경로로 로그아웃을 수행하며, 로그아웃 후에는 HTTP 세션을 무효화하여 사용자의 로그인 상태를 제거합니다.
@Bean PasswordEncoder passwordEncoder()
PasswordEncoder 인터페이스의 구현체를 빈으로 등록하는 메서드
BCryptPasswordEncoder는 강력한 해시 알고리즘을 사용하여 비밀번호를 안전하게 저장하고 인증하는 데 사용됩니다.
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long no;
private String id;
private String password;
private String name;
private String email;
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
private String tel;
private String zipCode;
private String address;
private String addressDetail;
private String delYn;
}
DB의 User 테이블과 매핑하는 객체
사용자의 데이터를 담는 용도로 사용할 예정입니다
주로 사용자 정보를 가져오고 저장하는데 사용
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class UserSignupForm {
// 회원 가입 양식을 처리한다 , 사용자 등록할 때 쓰인다
@NotBlank(message = "ID는 필수 입력값 입니다")
@Pattern(regexp = "^[a-z0-9]{5,20}$", message = "아이디는 영어 소문자와 숫자만 사용하여 5~20자리여야 합니다.")
private String id;
@NotBlank(message= "비밀번호는 필수 입력 값 입니디")
@Size(min = 8 , message = "비밀번호는 8글자 이상 입니다")
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[~!@#$%^&*()+|=])[A-Za-z\\d~!@#$%^&*()+|=]{8,16}$", message = "비밀번호는 8~16자 영문 대 소문자, 숫자, 특수문자를 사용하세요.")
private String password;
// @Pattern(regexp = "$expression") 정규식검증
@NotBlank(message = "이름은 필수 입력 값입니다")
@Pattern(regexp="^[가-힣]{2,}$", message = "이름은 한글 2글자 이상")
private String name;
@NotBlank(message="이메일은 필수 입력 값입니다")
@Email(message = "유효한 이메일 형식이 아닙니다")
private String email;
@NotBlank(message = "전화번호는 필수 입력 값입니다")
@Pattern(regexp="^\\d{2,3}-\\d{3,4}-\\d{4}$" , message = "유효한 전화번호 형식이 아닙니다")
private String tel;
private String zipCode;
private String address;
private String addressDetail;
public User toEntity(PasswordEncoder passwordEncoder) {
User user = new User();
user.setId(id);
user.setPassword(passwordEncoder.encode(password));
user.setName(name);
user.setEmail(email);
user.setTel(tel);
user.setZipCode(zipCode);
user.setAddress(address);
user.setAddressDetail(addressDetail);
return user;
}
}
사용자의 회원 가입할 때 입력하는 폼을 처리하기 위해 만든 클래스 입니다
사용자가 브라우저에서 회원가입시에 입력하는 정보들을 담고 있으며
사용자로부터 입력받은 데이터들을 유효성 검사하고 , 이것으로 객체를 생성해 DB에 저장하는데 사용됩니다
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class UserSignupForm {
// 회원 가입 양식을 처리한다 , 사용자 등록할 때 쓰인다
@Pattern(regexp = "^[a-z0-9]{5,20}$" , message ="알맞은 형식이 아닙니다") // message = "아이디는 영어 소문자와 숫자만 사용하여 5~20자리여야 합니다."
private String id;
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[~!@#$%^&*()+|=])[A-Za-z\\d~!@#$%^&*()+|=]{8,16}$" , message ="알맞은 형식이 아닙니다")
private String password;
// @Pattern(regexp = "$expression") 정규식검증
@Pattern(regexp="^[가-힣]{2,}$" , message ="알맞은 형식이 아닙니다")
private String name;
@Email(message = "유효한 이메일 형식이 아닙니다")
private String email;
// @Pattern(regexp="^\\d{2,3}-\\d{3,4}-\\d{4}$" , message = "유효한 전화번호 형식이 아닙니다")
private String tel;
private String zipCode;
private String address;
private String addressDetail;
public User toEntity(PasswordEncoder passwordEncoder) {
User user = new User();
user.setId(id);
user.setPassword(passwordEncoder.encode(password));
user.setName(name);
user.setEmail(email);
user.setTel(tel);
user.setZipCode(zipCode);
user.setAddress(address);
user.setAddressDetail(addressDetail);
return user;
}
}
유효성 검증 메세지가 너무 지저분하게 나와서 변경했습니다
@Setter
public class UserDetailsImpl implements UserDetails {
// 사용자의 인증 정보를 내타내는데 사용되며 사용자가 제공한 자격이 클래스의 정보와 일치하는지 확인한다
private String id;
private String password;
private Collection<? extends GrantedAuthority> authorities;
// 권한 반환
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return id;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
@Service
@RequiredArgsConstructor
public class UserService implements UserDetailsService {
private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder;
/*
사용자의 id 를 기반으로 사용자의 정보를 로드한다
해당 사용자의 정보를 UserDetails 객체로 반환하는데 , 실제 사용자의 정보를 포함하며
Spring Security 는 사용자의 인증 , 권한 부여를 처리한다
*/
/*
사용자 이름을 기반으로 사용자를 찾는다.
실제 구현에서는 검색이 대소문자를 구분하거나 구분하지 않을 수 있으며, 이는 구현 인스턴스가 구성된 방식에 따라 다를 수 있다.
사용자 이름을 식별하는 사용자의 데이터가 필요하다
사용자 레코드가 완전히 채워진 사용자 레코드를 반환. 반환된 객체는 null이 아니다
사용자를 찾을 수 없거나 사용자에게 부여된 권한이 없는 경우 UsernameNotFoundException을 발생
*/
/**
* 주어진 사용자 아이디를 기준으로 사용자의 데이터를 가져와 UserDetails 객체로 반환합니다.
* @param id 사용자 아이디
* @return UserDetails 객체
* @throws UsernameNotFoundException 주어진 아이디에 해당하는 사용자를 찾을 수 없는 경우 발생합니다.
*/
@Override
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
// 사용자 아이디를 기준으로 데이터베이스에서 사용자 정보를 가져옵니다. 이 정보는 user 객체에 저장
User user = userMapper.selectUserById(id);
// 데이터베이스에서 가져온 사용자 정보가 없다면(null이면) 예외를 발생시킵니다.
if(user == null) {
throw new UsernameNotFoundException("Id 찾을수 없습니다 : " +id);
}
// UserDetailsImpl 클래스의 객체를 생성합니다. 이 객체는 사용자의 인증 및 권한 정보를 제공하기위해 사용한다
UserDetailsImpl userDetails = new UserDetailsImpl();
// 객체에서 가져온 사용자 아이디와 비밀번호를 userDetails 객체에 설정
userDetails.setId(user.getId());
userDetails.setPassword(user.getPassword());
userDetails.setAuthorities(List.of(new SimpleGrantedAuthority("ROLE_USER")));
return userDetails;
}
/**
* 주어진 회원가입 폼 UserSignupForm 으로 사용자를 등록한다
* @param form 사용자 회원가입 폼 UserSignupForm
* @return 등록된 사용자
* @throws RuntimeException 이미 존재하는 아이디나 이메일일 경우 발생
*/
public User registerUser(UserSignupForm form) {
if (userMapper.selectUserById(form.getId()) != null) {
throw new RuntimeException("이미 존재하는 아이디입니다: " + form.getId());
}
if (userMapper.selectUserByEmail(form.getEmail()) != null) {
throw new RuntimeException("이미 존재하는 이메일 입니다: " + form.getEmail());
}
User user = form.toEntity(passwordEncoder);
userMapper.insertUser(user);
return user;
}
/**
* 주어진 번호에 해당하는 사용자를 데이터베이스에서 선택
* @param no 사용자 번호
* @return 선택된 사용자
* @throws RuntimeException 주어진 번호에 해당하는 사용자를 찾을 수 없는 경우 발생
*/
public User selectUserByNo(Long no) {
User user = userMapper.selectUserByNo(no);
if (user == null) {
throw new RuntimeException("해당 번호에 해당하는 사용자를 찾을 수 없습니다: " + no);
}
return user;
}
/**
* 주어진 아이디에 해당하는 사용자를 데이터베이스에서 선택
* @param id 사용자 아이디
* @return 선택된 사용자
* @throws RuntimeException 주어진 아이디에 해당하는 사용자를 찾을 수 없는 경우 발생
*/
public User selectUserById(String id) {
System.out.println(id);
User user = userMapper.selectUserById(id);
if (user == null) {
throw new RuntimeException("해당 아이디에 해당하는 사용자를 찾을 수 없습니다: " + id);
}
return user;
}
/**
* 주어진 이메일에 해당하는 사용자를 데이터베이스에서 선택
* @param email 사용자 이메일
* @return 선택된 사용자
* @throws RuntimeException 주어진 이메일에 해당하는 사용자를 찾을 수 없는 경우 발생
*/
public User selectUserByEmail(String email) {
User user = userMapper.selectUserByEmail(email);
if (user == null) {
throw new RuntimeException("해당 이메일에 해당하는 사용자를 찾을 수 없습니다: " + email);
}
return user;
}
/**
* id 중복 체크
* @param id DB에 저장되어있는 아이디
* @return 0 또는 1
*/
public int idCheck(String id) {
int cnt = userMapper.idCheck(id);
System.out.println("IdCnt : "+cnt);
return cnt;
}
/**
* email 중복 체크
* @param email DB에 저장되어있는 이메일
* @return 0 또는 1
*/
public int emailCheck(String email) {
int cnt = userMapper.emailCheck(email);
System.out.println("EmailCnt : " + cnt);
return cnt;
}
}
@Controller
@RequiredArgsConstructor
@RequestMapping("/user")
public class UserController {
private final UserService userService;
@GetMapping("/register")
public String registerForm(Model model) {
model.addAttribute("userSignupForm", new UserSignupForm());
return "user/registerForm";
}
@PostMapping("/join")
public String userJoin(@ModelAttribute("userSignupForm")
@Valid UserSignupForm form ,
BindingResult errors ) {
// BindingResult객체에 오류가 있다면 , 유효성 체크를 통과하지 못한 것임으로 ,
// 회원가입 폼으로 내부 이동 시킨다.
if (errors.hasErrors()) {
return "user/registerForm";
}
try {
User user = userService.registerUser(form);
return "redirect:/user/completed?id=" + user.getId();
} catch (RuntimeException ex) {
String message = ex.getMessage();
if("id".equals(message)) {
errors.rejectValue("id", null,"사용 할 수 없는 아이디");
} else if( "email".equals(message)) {
errors.rejectValue("email", null, "사용 할 수 없는 이메일");
}
return "user/registerForm";
}
@GetMapping("/completed")
public String completed(String id , Model model) {
User user = userService.selectUserById(id);
model.addAttribute("user",user);
return "user/completed";
}
}
https://dev-coco.tistory.com/123
728x90
'Back_End > SpringBoot' 카테고리의 다른 글
마이페이지 ver.1- SpringSecurity, MySQL , MyBatis @PreAuthorize("isAuthenticated()") (0) | 2024.04.22 |
---|---|
시큐리티로 로그인한 회원 정보 조회 , 수정 - SpringSecurity, MySQL , MyBatis (0) | 2024.04.17 |
로그아웃 - SpringSecurity, MySQL , MyBatis (0) | 2024.04.17 |
로그인 SpringSecurity, MySQL , MyBatis (0) | 2024.04.15 |
Regex를 활용한 입력 유효성 검사 (0) | 2024.04.09 |