[스프링부트]Spring Security

송송승현's avatar
Nov 28, 2024
[스프링부트]Spring Security

정의

💡
애플리케이션의 보안을 담당하는 강력한 프레임워크
인증(Authentication)과 인가(Authorization)를 통해 애플리케이션을 보호하는데 사용

인증(Authentication)

  • 사용자가 누구인지 확인
  • 일반적으로 사용자가 입력한 아이디와 비밀번호를 검증하여 사용자의 신원을 확인

인가(Authorization)

  • 인증된 사용자가 애플리케이션에서 무엇을 할 수 있는지 결정
  • 사용자에게 특정 리소스에 대한 접근 권한이 있는지 확인

주요 구성

Security Context

  • 현재 인증된 사용자와 관련된 보안 정보를 저장하는 컨텍스트
  • SecurityContextHolder를 통해 접근 가능

Security Filter Chain

  • 여러가지 보안 필터로 구성된 체인
  • HTTP 요청이 이 필터 체인을 통과하면서 검사

UserDetailsService

  • 사용자 정보를 로드하는 서비스 인터페이스
  • loadUserByUsername() 메서드를 사용해서 데이터베이스에서 정보 조회

PasswordEEncoder

  • 비밀번호를 암호화 하는 인터페이스

AuthenticationManager

  • 인증을 처리하는 주요 인터페이스
  • authenticate() 메서드를 통해 사용자의 자격 증명을 검증

예제

import com.metacoding.authblog.user.UserService; import lombok.RequiredArgsConstructor; 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.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; @Configuration public class SecurityConfig { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain config(HttpSecurity http) throws Exception { http.csrf(c->c.disable()); http.authorizeHttpRequests(r -> r.requestMatchers("/s/**").authenticated() .anyRequest() .permitAll()) .formLogin(f ->f.loginPage("/login-form") .loginProcessingUrl("/login") .defaultSuccessUrl("/") .permitAll()); return http.build(); } } @Entity @Table(name = "user_tb") @AllArgsConstructor @NoArgsConstructor @Getter public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(unique = true, nullable = false) private String username; @Column(nullable = false) private String password; @Column(nullable = false) private String email; @CreationTimestamp private Timestamp createdAt; @Override public String getUsername() { //계정의 고유한 값을 리턴(중복이없는 값) return username; } @Override public String getPassword() { //계정의 비밀번호를 리턴 return password; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return List.of(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } } @Data public class JoinDTO { private String username; private String password; private String email; public User toEntity(PasswordEncoder passwordEncoder) String encodedPassword = passwordEncoder.encode(password); System.out.println(encodedPassword); User user = new User(null, username, encodedPassword, email, null); return user; } } @Controller @RequiredArgsConstructor public class UserController { private final UserService userService; @GetMapping("/login-form") public String loginForm() { return "user/login-form"; } @PostMapping("/join") public String join(UserRequset.JoinDTO joinDTO) { userService.회원가입(joinDTO); return "redirect:/login-form"; } } import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor public class UserService implements UserDetailsService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; // post 요청 // login일때 호출 // key 값 -> username, password // content-type -> x-www-form-urlencoded @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("loadUserByUsername"); User user = userRepository.findByUsername(username); return user; } @Transactional public void 회원가입(UserRequset.JoinDTO joinDTO){ userRepository.save(joinDTO.toEntity(passwordEncoder)); } } @RequiredArgsConstructor @Repository public class UserRepository { private final EntityManager em; public User save(User user) { em.persist(user); return user; } }
Share article

송승현의 블로그