모임 웹 프로젝트는 회원이 아니면 사이트에 접속을 할 수 없게 만들예정입니다.. 따라서 스프링 시큐리티를 이용하여 권한을 설정하고 회원이 아니면 접속을 차단하는 기능을 구현을 하겠습니다.
1. Spring Security 기본 개념
Spring Security는 애플리케이션의 보안 문제를 해결하기 위해 인증과 인가를 제공하는 프레임워크입니다. 인증은 사용자가 누구인지 확인하는 과정이고, 인가는 사용자가 특정 리소스에 접근할 권한이 있는지를 확인하는 과정입니다.
- 인증(Authentication): 사용자가 시스템에 로그인을 시도할 때 사용자의 신원을 확인합니다. 로그인 페이지를 통해 사용자의 이름(username)과 비밀번호(password)를 입력받고, 이 정보를 바탕으로 사용자가 등록된 사용자(회원)인지 확인하는 과정을 의미합니다.
- 인가(Authorization): 인증이 완료된 후, 특정 리소스나 기능에 접근할 수 있는지 권한을 확인합니다. 예를 들어, 관리자만 접근할 수 있는 페이지나, 로그인한 사용자만 이용 가능한 서비스에 대한 접근을 제한할 수 있습니다
스프링 시큐리티를 이용하여 회원이 아닌 사용자가 웹 어플리케이션에 접속할려고 할때 이를 차단하여 인증되지 않는 사용자를 특정 경로에 접근할 수 없도록 설정할 예정이다. 그러면 관련 로직들을 설명하겠습니다.
인증되지 않은 사용자의 접근 차단: Spring Security는 인증되지 않은 사용자가 보호된 리소스에 접근하려고 할 때 자동으로 로그인 페이지로 리다이렉트합니다. 인증이 완료된 후에만 사용자가 보호된 리소스에 접근할 수 있게 됩니다.
인증된 사용자와 비회원 구분: 인증된 사용자는 UserDetailsService를 통해 데이터베이스에서 사용자 정보를 로드하여 인증을 수행하고, 이를 통해 회원 여부를 판단합니다. 회원이 아닌 경우, 인증이 성공적으로 이루어지지 않기 때문에 보호된 리소스에 접근할 수 없습니다.

그럼 이제 스프링 시큐리티 설정과 회원 엔티티를 구성하겠습니다.
먼저 user엔티티 입니다.
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "uid", nullable = false)
private String uid;
@Column(name = "user_name", nullable = false) // 사용자 이름, null 불가
private String name;
@Column(nullable = false, unique = true) // 이메일은 null 불가, 고유 값으로 설정
private String email;
@Column(nullable = false) // 비밀번호는 null 불가
private String password;
@Column
private String nickname;
@Column(name = "birth_date")
private LocalDate birthDate;
@Column(name = "registration_date")
private LocalDate regidate;
@Column
private String gender;
@Column
private String introduce;
@Column(nullable = false)
private String role;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<ProfileImage> profileImages;
@OneToMany(mappedBy = "user" , cascade = CascadeType.ALL)
private List<Interest> interests;
@Builder
public User(String name, String email,String password, String nickname,LocalDate birthDate, String gender, String introduce, String roleUser,String uid) {
this.uid = uid;
this.name = name;
this.email = email;
this.password = password;
this.nickname = nickname;
this.birthDate = birthDate;
this.gender = gender;
this.introduce = introduce;
this.role = roleUser;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of();
}
@Override
public String getUsername() {
return "";
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
프로필사진인 profileImages와 관심사 interests 는 여러개의 항목을 받기 위해 일대다 관계를 구현을 하여 테이블 조인을 하였습니다.
조인된 테이블인 ProfileImage와 Interest 입니다
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ProfileImage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String imageUrl;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Interest {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String interestName;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
User엔티티를 자세하게 보시면 Userdetails라는 인터페이스를 상속한 걸 보실 수 있습니다.
userdetails 상속하여 스프링 시큐리티가 사용자의 인증 과정을 처리 할 수 있게 해줍니다. 이 인터페이스를 통해 사용자의 인증 상태, 권한 정보 등을 관리할 수 있기 때문에, 이를 상속하여 사용자의 데이터를 Spring Security의 인증 시스템에 통합할 수 있습니다.
다음으로 Spring Security에서 사용자의 인증을 처리하는 서비스 클래스인 UerdetailService를 작성하겠습니다.
@RequiredArgsConstructor
@Service
public class UserDetailService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public User loadUserByUsername(String uid) {
return userRepository.findByUid(uid)
.orElseThrow(() -> new IllegalArgumentException((uid)));
}
}
userdetailservice 인터페이스를 상속한 서비스 클레스를 하나 만들어 줍니다.
여기선 loadUserByUsername이라는 메서드를 이용하여 사용자의 이름 또는 ID(uid)를 기준으로 데이터베이스에서 사용자 정보를 조회 합니다. 사용자가 로그인을 시도할 때, 이 메서드는 입력된 uid 값을 받아서 해당하는 사용자를 조회합니다.
사용자를 조회 한 뒤 user 객체를 반환을 하여 인증을 처리합니다.
다음으로 데이터 베이스와 연결 해 줄 userepository인터페이스를 만들어 준다.
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUid(String Uid);
}
마지막으로 가장 중요한 스프링시큐리티를 사용하여 웹 애플리케이션의 보안 설정을 구성하는 클래스를 구현하겠습니다. 이 클래스는 인증(Authentication)과 인가(Authorization)를 관리하며, 로그인, 로그아웃, 암호화, 보안 필터 등 보안 관련 요소들을 설정합니다. 구현 한 뒤 각 구성요소에 대해 간략하게 설명하겠습니다.
@RequiredArgsConstructor
@Configuration
public class WebSecurityConfig {
private final UserDetailService userService;
@Bean
public WebSecurityCustomizer configure() {
return (web) -> web.ignoring()
.requestMatchers("/static/**");
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeRequests()
.requestMatchers("/login", "/signup", "/user","image/*").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/articles")
.and()
.logout()
.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.and()
.csrf().disable()
.build();
}
@Bean
public AuthenticationManager authenticationManager(HttpSecurity http, BCryptPasswordEncoder bCryptPasswordEncoder, UserDetailService userDetailService) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userService)
.passwordEncoder(bCryptPasswordEncoder)
.and()
.build();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
@Configuration
이 클래스가 Spring의 설정 클래스임을 나타냅니다. Spring Boot 애플리케이션에서 보안 관련 설정을 관리하기 위해 사용됩니다
WebSecurityCustomizer
정적 리소스(예: /static/**)에 대해서는 보안 검사를 제외하는 설정입니다. 즉, CSS, JS, 이미지 파일과 같은 리소스는 인증 없이도 접근할 수 있도록 설정합니다.
SecurityFilterChain
HTTP 보안 설정을 정의하는 메서드입니다. 주요 역할은 페이지별 접근 권한 설정: /login, /signup, /user, image/*와 같은 페이지는 모든 사용자에게 허용(permitAll)되고, 그 외 페이지는 인증된 사용자만 접근 가능하도록 설정합니다.
로그인/로그아웃 설정: 커스텀 로그인 페이지(/login)를 지정하고, 성공 시 /articles로 이동합니다. 로그아웃 시에는 /login으로 리다이렉트하고, 세션을 무효화합니다.
AuthenticationManager
Spring Security의 인증 매니저를 설정하는 메서드로, 사용자 인증 처리에서 중요한 역할을 합니다.
BCryptPasswordEncoder
비밀번호 암호화를 위한 BCrypt 해시 함수입니다. 사용자의 비밀번호를 안전하게 저장하고 비교할 때 사용됩니다.
참고로 가장 기본적이지만 은근 모르는 사람이 많은 아주 중요한 사실인데
제7조 개인정보의 암호화① 개인정보처리자는 비밀번호, 생체인식정보 등 인증정보를 저장 또는 정보통신망을 통하여 송ㆍ수신하는 경우에 이를 안전한 암호 알고리즘으로 암호화하여야 한다. 다만, 비밀번호를 저장하는 경우에는 복호화되지 아니하도록 일방향 암호화하여 저장하여야 한다.
비밀번호 암호화는 선택이 아니라 필수였습니다. 저는 처음 구현할때 책보고 구현했어서 이런 사실을 몰랐는데 나중에 보니까 이게 법으로 정해져있더라구요. 제가 국비학원에서 프로젝트 할 때 많은 사람들이 모르고 있어서 추가해봤습니다.
'project > 모임웹프로젝트' 카테고리의 다른 글
| 모임 웹 프로젝트 회원가입 백엔드 구성 (6) (0) | 2024.09.29 |
|---|---|
| 모임 웹 프로젝트 회원가입 코드수정 (5) (0) | 2024.09.29 |
| 모임 웹 프로젝트 프런트 구성2 (4) (1) | 2024.09.28 |
| 모임웹프로젝트 회원가입페이지 프런트 구성1 (3) (9) | 2024.09.28 |
| 모임웹프로젝트 기획(1) (2) | 2024.09.28 |