Security 회원 가입
User Entity
package com.example.security1.model;
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import java.sql.Timestamp;
@Entity
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String username;
@Column
private String password;
@Column
private String email;
@Column
private String role;
@CreationTimestamp
private Timestamp createDate;
}
UserRepository
package com.example.security1.repository;
import com.example.security1.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
//@Repository라는 어노테이션이 없어도 IoC가 된다. JpaRepository를 상속했기 때문
public interface UserRepository extends JpaRepository<User, Long> {
}
JpaRepository를 상속했기 때문에 @Repository 어노테이션이 없어도
IoC가 된다.
IndexController
package com.example.security1.controller;
import com.example.security1.model.User;
import com.example.security1.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller //View를 return
public class IndexController {
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
//localhost:8080/
//localhost:8080
@GetMapping({"","/"})
public String index() {
// 머스테치 기본폴더 src/main/resources/
// 뷰리졸버 설정 : templates (prefix), .mustache (suffix) 생략가능
return "index"; // src/main/resources/templates/index.mustache
}
@GetMapping("/user")
public @ResponseBody String user() {
return "user";
}
@GetMapping("/admin")
public @ResponseBody String admin() {
return "admin";
}
@GetMapping("/manager")
public @ResponseBody String manager() {
return "manager";
}
//SecurityConfig 를 생성후 자동으로 SpringSecurity에 의해 나오던 로그인 화면이 나오지 않게 된다.
@GetMapping("/loginForm")
public String login() {
return "loginForm";
}
@GetMapping("joinForm")
public String joinForm() {
return "joinForm";
}
@PostMapping("/join")
public String join(User user) {
user.setRole("ROLE_USER");
System.out.println(user);
userRepository.save(user);
/* 회원가입은 잘되지만 비밀번호는 1234
=> 시큐리티로 로그인 할 수 없다.
이유는 패스워드가 암호화가 안되었기 때문이다.
*/
return "redirect:/loginForm";
//redirect: 를 붙이면 /loginForm이라는 함수를 호출한다.
}
}
user의 값을 확인하기 위해 System.out.println(user);를 해주었다.
SecurityConfig
package com.example.security1.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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity // 스프링 시큐리티 필터(SecurityConfig)가 스프링 필터체인에 등록이 된다.
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeHttpRequests()
.requestMatchers("/user/**").authenticated()
.requestMatchers("/manager/**").hasAnyRole("ADMIN", "MANAGER")
.requestMatchers("/admin/**").hasAnyRole("ADMIN")
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/loginForm");
return http.build();
}
}
loginPage를 controller에 맞게
"/loginFrom"으로 변경해 주었다.
joinForm.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 페이지</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<hr/>
<form action="/join" method = "POST">
<input type = "text" name = "username" placeholder="Username"/> <br/>
<input type = "password" name = "password" placeholder="Password"/> <br/>
<input type = "email" name = "email" placeholder="Email"/> <br/>
<button>회원가입</button>
</form>
</body>
</html>
회원가입을 하면 "/join"으로 "POST" 요청을 보낸다.
username, password, email의 정보로 회원가입 페이지를 만들었다.
loginForm.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 페이지</title>
</head>
<body>
<h1>로그인 페이지</h1>
<hr/>
<form>
<input type = "text" name = "username" placeholder="Username"/> <br/>
<input type = "password" name = "password" placeholder="Password"/> <br/>
<button>로그인</button>
</form>
<a href = "/joinForm">회원가입을 아직 하지 않음</a>
</body>
</html>
"/joinForm"을 해주어 회원가입을 하지 않았다면
회원가입을 할 수 있는 페이지로 연결되게 하였다.
test
"회원가입을 아직 하지 않음"을 클릭하면
회원가입 페이지로 이동한다.
리다이렉트로 로그인페이지를 지정해 주었기 때문에
회원가입을 클릭하면 로그인 페이지로 이동된다.
username, password, email, role이 잘 입력되었다.
id는 null이지만, GenerationType.IDENTITY로 했기 때문에
DB에 저장될 때 id가 자동으로 정해진다.
하지만 비밀번호가 그대로 1234로 들어가게 되어
시큐리티로 로그인할 수 없다.
이유는 암호화가 되어있지 않기 때문이다.
SecurityConfig에 BCryptPasswordEncoder를 추가
package com.example.security1.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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity // 스프링 시큐리티 필터(SecurityConfig)가 스프링 필터체인에 등록이 된다.
public class SecurityConfig {
@Bean //해당 메서드의 리턴되는 오브젝트를 IoC로 등록해 준다.
public BCryptPasswordEncoder encodePwd() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeHttpRequests()
.requestMatchers("/user/**").authenticated()
.requestMatchers("/manager/**").hasAnyRole("ADMIN", "MANAGER")
.requestMatchers("/admin/**").hasAnyRole("ADMIN")
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/loginForm");
return http.build();
}
}
IndexController의 join() 메서드에 인코더 추가
package com.example.security1.controller;
import com.example.security1.model.User;
import com.example.security1.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller //View를 return
public class IndexController {
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
//localhost:8080/
//localhost:8080
@GetMapping({"","/"})
public String index() {
// 머스테치 기본폴더 src/main/resources/
// 뷰리졸버 설정 : templates (prefix), .mustache (suffix) 생략가능
return "index"; // src/main/resources/templates/index.mustache
}
@GetMapping("/user")
public @ResponseBody String user() {
return "user";
}
@GetMapping("/admin")
public @ResponseBody String admin() {
return "admin";
}
@GetMapping("/manager")
public @ResponseBody String manager() {
return "manager";
}
//SecurityConfig 를 생성후 자동으로 SpringSecurity에 의해 나오던 로그인 화면이 나오지 않게 된다.
@GetMapping("/loginForm")
public String login() {
return "loginForm";
}
@GetMapping("joinForm")
public String joinForm() {
return "joinForm";
}
@PostMapping("/join")
public String join(User user) {
user.setRole("ROLE_USER");
System.out.println(user);
/* 회원가입은 잘되지만 비밀번호는 1234
=> 시큐리티로 로그인 할 수 없다.
이유는 패스워드가 암호화가 안되었기 때문이다.
*/
String rawPassword = user.getPassword();
String encPassword = bCryptPasswordEncoder.encode(rawPassword);
user.setPassword(encPassword);
userRepository.save(user);
return "redirect:/loginForm";
//redirect: 를 붙이면 /loginForm이라는 함수를 호출한다.
}
}
print결과는 다른 것이 없다.
하지만 DB에 저장될 때 password가 암호화가 되어 저장되었다.
'자바 탐구' 카테고리의 다른 글
스프링) SpringSecurity - 5) Security 권한 처리 (0) | 2023.05.26 |
---|---|
스프링) SpringSecurity - 4) Security 로그인 (0) | 2023.05.26 |
스프링) SpringSecurity - 2) SecurityConfig 설정 (0) | 2023.05.26 |
스프링) SpringSecurity - 1) Security, Mustache 환경 설정 (0) | 2023.05.26 |
JPA) Entity의 연관 관계 - @ManyToMany - (0) | 2023.05.03 |