본문 바로가기

Spring Boot/Security

[SpringBoot Security] 로그인 페이지 만들기

해당 글은 전 페이지 기준으로 이어서 진행 중임

 

첫번째 - 로그인 페이지 Action 설정

1.HTML 수정 ㄱㄱ

form 태그에 action, method 속성(attribute) 추가

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
	<title>로그인 페이지</title>
</head>
<body>
	<h1>로그인 페이지</h1>
	<form action="/login" method="POST">
		<input type="text" name="username" placeholder="UserNmae"><br/>
		<input type="password" name="password" placeholder="password"><br/>
		<button>로그인</button>
	</form>
	
	<a href="/joinForm">아이디가 없음 ?</a>
</body>
</html>

 

2.SecurityConfig Class -> configure Method -> 코드 추가 ㄱㄱ

// 추가된 메서드
.loginProcessingUrl("/login")
.defaultSuccessUrl("/")

 

-----------------------------------------------------------------------------------------------------------------------------------

멈춰 !

전달 사항
- 시큐리티가 "/login" 주소 요청을 낚아채서 로그인을 진행함
- 로그인이 진행이 되면서 자신만의 session 공간을 가지는데 그 공간을 "Security ContextHolder"라고 함
- Security ContextHolder 키 값에 들어갈 수 있는 오브젝트가 정해져 있음 => Authentication
- Authentication 안에는 User 정보가 있어야함
- User 정보의 오브젝트 타입이 정해져 있음  = UserDetails 객체

 

정리
- 시큐리티 세션 영역이 있는데 해당 영역에 들어갈 수 있는 객체는 Authentication
- Authentication 안에 들어갈 수 있는 데이터 타입은 UserDetails 

 

흐름
- Security ContextHolder -> Authentication -> UserDetails

 

객체지향적으로다가

Security ContextHolder( Authentication ( UserDetails( ) ) );

-----------------------------------------------------------------------------------------------------------------------------------

 

두번째 - UserDetails 만들기
    :Security ContextHolder -> Authentication -> UserDetails

1.패키지 생성 ㄱㄱ (auth)

 

2.클래스 생성 ㄱㄱ (PrincipalDetails)

3.PrincipalDetails (UserDetails) -> 코드 작성 ㄱㄱ

package com.goodbam.security1.config.auth;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.goodbam.security1.model.User;

public class PrincipalDetails implements UserDetails{

	// User 정보를 들고있는 녀석
	private User user; 
	
    // 딱 봐도 생성자
	public PrincipalDetails(User user) {
		this.user = user;
	}
	
	// User의 권한을 리턴
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		Collection<GrantedAuthority> collect = new ArrayList<>();
		
		collect.add(new GrantedAuthority() {
			@Override
			public String getAuthority() {
				return user.getRole();
			}
		});
		
		return collect;
	}

	@Override
	public String getPassword() {
		return user.getPassword();
	}

	@Override
	public String getUsername() {
		return user.getUsername();
	}

	// 계정 만료 여부를 확인해?
    // flase -> 응 true -> 아니
	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	// 계정 잠김 여부를 확인해?
	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	// 계정 비밀번호 변경을 오래동안 안하면 물어볼까?
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	// 너 계정 활성화 되어 있니?
	@Override
	public boolean isEnabled() {

		return true;
	}

}

 

 

세번째 - Authentication 만들기
    :Security ContextHolder -> Authentication -> UserDetails

1. 클래스 생성 ㄱㄱ ( PrincipalDetailsService ) 

 

2.PrincipalDetailsService 오버라이딩 ㄱㄱ

package com.goodbam.security1.config.auth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.goodbam.security1.model.User;
import com.goodbam.security1.repository.UserRepository;

@Service
public class PrincipalDetailsService implements UserDetailsService{

	@Autowired
	private UserRepository userRepository;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		
		User userEntity = userRepository.findByUsername(username);
		
		if(userEntity != null) {
			return new PrincipalDetails(userEntity);
		}
		
		return null;
	}

}

 

3.UserRepository Interface -> findUserName Method 추가 ㄱㄱ

 

4.흐름 정리 ㄱㄱ

    :로그인 버튼 클릭 -> Action="/login" 실행 -> 스프링 IoC 컨테이너에서 UserDetailsService로 등록되어있는 클래스
    를 찾음 -> UserDetailsService 안에 있는 loadUserByUsername 메서드를 실행 시킴 -> 파리미터를 넘겨 줌

 

네번째 - 로그인 테스트

1.회원가입 ㄱㄱ

2.로그인 ㄱㄱ

3.로그인 성공 !