-
Security Session스프링/스프링 시큐리티 2024. 1. 8. 20:09
SecurityConfig.class
@Configuration @EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록이 된다. public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf(CsrfConfigurer::disable); http.authorizeHttpRequests(authorize -> authorize .requestMatchers("/user/**").authenticated() .requestMatchers("/manager/**").hasAnyRole("ADMIN", "MANAGER") .requestMatchers("/admin/**").hasAnyRole("ADMIN") .anyRequest().permitAll() ); http.formLogin(formLogin -> formLogin .loginPage("/loginForm") .loginProcessingUrl("/login") // login 주소가 호출되면 시큐리티가 낚아채서 대신 로그인 진행 .defaultSuccessUrl("/")); // 로그인 시 기존의 페이지로 접근 // 만약에 로그인이 안된 상황에서 user에 접근하다 loginForm으로 튕겨지면 // 다시 로그인 시 root 페이지가 아니라 user path로 접근 return http.build(); } }
SecurityConfig에서 loginForm 페이지에서 로그인을 통해 login 페이지를 호출하면 스프링 시큐리티가 낚아채서 대신 로그인을 진행하는 부분을 추가했다.
시큐리티가 /login 주소 요청이 오면 낚아채서 로그인을 진행시켜주는데, 진행이 완료되면 시큐리티 session을 만들어준다. 이 때의 오브젝트 타입은 Authentication 타입 객체이다.
Authentication 안에 User의 정보가 있어야하는데, 이 때의 User 오브젝트 타입은 UserDetails 타입의 객체이다.
쉽게 말하면 시큐리티 세션이 있는데 여기 들어갈 수 있는 객체가 Authentication 객체이다.
이 객체 안에 user를 저장하는 것은 UserDetails 객체인 것이다.
나중에 꺼내서 사용할 때에 Session에서 Authentication 객체를 꺼내고, 그 안에서 UserDetails 객체를 꺼내면 user의 object에 접근할 수 있는 것이다.
PrincipalDetails.class
public class PrincipalDetails implements UserDetails { // UserDetails를 implements 했으니 // Security Session => Authentication => UserDetails(PrincipalDetails) private User user; public PrincipalDetails(User user) { this.user = user; } // 해당 User의 권한을 리턴 @Override public Collection<? extends GrantedAuthority> getAuthorities() { // 해당 반환타입으로 변환을 위해 collect라는 ArrayList를 만들고 안에 user.getRole()을 넣기 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(); } // 계정이 만료되었으면 false @Override public boolean isAccountNonExpired() { return true; } // 계정이 잠겨있으면 false @Override public boolean isAccountNonLocked() { return true; } // 자격 증명이 만료되었으면 false @Override public boolean isCredentialsNonExpired() { return true; } // 계정이 활성화되지 않았으면 false @Override public boolean isEnabled() { return true; } }
위의 코드에서는 UserDetails를 implement 했으니 PrincipalDetails에서 user의 object에 접근할 수 있다.
PrincipalDetialsService.class
@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; } }
시큐리티 설정에서 loginProcessingUrl("/login"); 이라고 된 부분이 있다.
위의 코드는 login 요청이 오면 자동으로 UserDetailsService 타입으로 IoC 되어있는 loadUserByName 함수가 실행되는 것이다.
만약에 userEntity가 없으면 null을 반환하고 userEntity가 있다면 PrincipalDetials에 userEntity를 넣어서 반환해준다.
이 값들이 스프링 시큐리티의 session에 들어가는 것이다.
loginForm에서 로그인 버튼을 누르면 <form action="/login"method="POST">를 통해 /login이 요청이 되는데, 스프링 시큐리티는 UserDetailsSerivce가 implement 되어있는 PrincipalDetailsService를 찾아서 loadUserByUsername을 호출한다.
이러한 방식으로 로그인을 진행하면 세션에 user의 object가 담기는 것이다.
'스프링 > 스프링 시큐리티' 카테고리의 다른 글
OAuth - 구글 로그인(Authentication 객체가 가지는 2가지 타입) (0) 2024.01.09 OAuth - 구글 로그인(구글 api를 통해 회원 프로필 받아오기) (0) 2024.01.09 시큐리티 권한처리 (0) 2024.01.08 회원가입 시 비밀번호 암호화 (0) 2024.01.08 스프링 필터 - 권한 있는 사람만 접근 (0) 2024.01.08