Search
Duplicate
📒

[Spring Security] 01-3. 실습 - form 회원가입

상태
미진행
수업
Spring Security
주제
Security
4 more properties
참고

시큐리티 로그인, 회원가입

NOTE
시큐리티를 이용해서 회원가입을하고 로그인을 한다!

회원가입, 컨트롤러 및 화면구성

NOTE

controller

@GetMapping("/joinForm") public String joinForm() { return "joinForm"; } @PostMapping("/join") public String join(User user) { System.out.println(user); user.setRole("ROLE_USER"); String rawPassword = user.getPassword(); String encPassword = bCryptPasswordEncoder.encode(rawPassword); user.setPassword(encPassword); // 회원가입 잘됨. 비밀번호 : 1234 => 시큐리티로 로그인할 수 없음 ( 패스워드가 암호화 되지 않아서) userRepository.save(user); return "redirect:/loginForm"; }
Java
복사
user 정보를 받아서, 권한을 넣어주고 비밀번호를 암호화한다.

joinForm

<!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>
HTML
복사
input의 username은 꼭 저렇게 작성해야 한다!

로그인, 권한처리

NOTE
로그인을 구현하기 위해서 auth 패키지를 생성한다!
auth패키지는 Spring Security가 로그인을 진행하고 완료가되면 Security Session을 만들어준다.
Session에 들어가는 정보 Object가 정해져있는데, 이것이 바로 Authentication 객체여야 한다.
Spring Security ⇒ Authentiaction ⇒ UserDetails 객체 이렇게 구성된다.

로그인, 컨트롤러 및 화면구성

NOTE

controller

@GetMapping("/loginForm") public String loginForm() { return "loginForm"; }
Java
복사

loginForm

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>로그인 페이지</title> </head> <body> <h1>로그인 페이지</h1> <hr/> <!-- 시큐리티는 x-www-form-url-encoded 타입만 인식 --> <form action="/login" method="post"> <input type="text" name="username" /> <input type="password" name="password" /> <button>로그인</button> </form> <a href="/joinForm">회원가입을 아직 하지 않으셨나요?</a> </body> </html>
HTML
복사

PrincipalDetails

NOTE
UserDetails 객체를 상속받으면 스프링 시큐리티의 고유한 세션저장소에 저장을 할 수 있게 된다!
@RequiredArgsConstructor public class PrincipalDetails implements UserDetails { private final User user; // 해당 User의 권한을 리턴하는 곳 @Override public Collection<? extends GrantedAuthority> getAuthorities() { Collection<GrantedAuthority> collect = new ArrayList<>(); collect.add(()->{ return user.getRole();}); return collect; } @Override public String getPassword() { return user.getPassword(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { // 우리 사이트 1년동안 로그인안하면 휴먼계정으로 변한다 // 로그인한 날짜가 마지막 로그인 시간 1년초과하면 false return true; } }
Java
복사
스프링 시큐리티가 대신 로그인을 해주는 대신 패스워드를 가로채기 한다.
이렇게 된 PricipaDetails 타입을 Authentication객체 안에 넣는다.

PrincipalDetailsService

NOTE
인증 시, DB에서 User를 찾고 UserDetails로 반환하는 loadUserByUsername 메서드를 갖는다.
// 시큐리티 설정에서 loginProcessingUrl("/login") // login 요청이 오면 자동으로 UserDetailService 타입으로 Ioc 되어있는 loadUserByUserName 함수가 실행 @Service @RequiredArgsConstructor public class PrincipalDetailsService implements UserDetailsService { private final UserRepository userRepository; // 시큐리티 session = Authentication(내부 UserDetails) = UserDetails @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("username = " + username); User userEntity = userRepository.findByUsername(username); if (userEntity != null) { return new PrincipalDetails(userEntity); } return null; } }
Java
복사
Authentication객체를 생성하기 위해서 PrincipalDetailsService class를 생성한다.
UserDetailsService를 상속하여 정의한다.
로그인 요청이 오면 자동으로 loadUserByUsername함수가 실행되도록 정의되어 있다.
이 때 매개변수로 받는 String username은 html에서 정의된 input type의 name과 동일해야 한다!

권한처리

NOTE
User의 정보에는 ROLE이라는 변수가 있으며, 이 권한에 따라 사용자가 들어갈 수 있는 페이지를 처리할 수 있다.
각 유저는 권한이 다르다.

EnableWebSecurity

@Configuration @EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록된다! @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) // secure 어노테이션 활성화, preAuthorize, postAUthorize 활성화 public class SecurityConfig { ... }
Java
복사
@Secured("ROLE_ADMIN") @GetMapping("/info") public @ResponseBody String info(){ return "개인정보"; }
Java
복사
하나의 권한을 걸 때 유용하게 사용이 가능하다

EnableGlobalMethodSecurity

@Configuration @EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록된다! @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) // secure 어노테이션 활성화, preAuthorize, postAUthorize 활성화 public class SecurityConfig { ... }
Java
복사
@PreAuthorize("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')") @GetMapping("/data") public @ResponseBody String data(){ return "데이터정보"; }
Java
복사