@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/user/**").authenticated() // user 페이지에는 권한 필요
                .antMatchers("/manager/**").access("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')") // manager페이지에 필요한 권한
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") // admin페이지에 필요한 권한
                .anyRequest().permitAll() // 모든 요청은 권한 허가
                .and()
                .formLogin()
                .loginPage("/loginForm")
                // 로그인 관련 추가
                .loginProcessingUrl("/login")
                // 로그인 성공시 이동할 페이지
                .defaultSuccessUrl("/");
        return http.build();
    }
<form action="/join" method="POST">
public class PrincipalDetails implements UserDetails {
    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();
    }
    // 계정이 만료되지 않았는지?
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    // 계정이 잠겼는가?
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    // 계정 암호 등이 안전한가?
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
	
    // 계정이 유효한가? 
    @Override
    public boolean isEnabled() {
        //우리 사이트는 1년동안 회원 로그인을 안하면 휴면 계정으로 하기로 함!!!
        // 현재시간 - 로그인 시간 = 1년이상이면 휴면 계정으로 전환
        return true;
    }
}
@Service
public class PrincipalDetailsService implements UserDetailsService {
    private UserRepository userRepository;
    public PrincipalDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    // 중요!!!
    // 여기서 username과 loginForm.html의 username과 이름이 동일하게 username이어야 한다.
    // 중요!!
    // Security Session(Authentication(UserDetails))
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username = " + username);
        User user = userRepository.findByUsername(username);
        if (user != null) {
            return new PrincipalDetails(user);
        }
        return null;
    }
}
// SecurityConfig에 아래의 코드를 추가해주자
  .usernameParameter("newName");@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User userEntity = userRepository.findByUsername(username);
        return null;
    }
public interface UserRepository extends JpaRepository <User, Integer> {
    // Jpa Query 메서드 규칙
    // findBy는 규칙 -> Username문법
    // select * from user where username = :username
    public User findByUsername(String username);
}
@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
        User userEntity = userRepository.findByUsername(username);
        
        if(userEntity!=null){
        
        	return new PrincipalDetails(userEntity);
        }
    }
http://localhost:8080/user



				.loginPage("/loginForm")
                // 로그인 관련 추가
                .loginProcessingUrl("/login")
                // 로그인 성공시 이동할 페이지
                .defaultSuccessUrl("/");