지난 뽀-스트
https://udangtang-dev.tistory.com/6
[ Java ] 자바에서 구현 해볼 수 있는 로그인 기법-1 ( 세션 기반 로그인 )
이번 포스팅에서는 자바에서 써먹을 수 있는 로그인 방법을 끄적여 볼까 한다.1. Session-based Authentication세션 기반 로그인은 웹 애플리케이션에서 사용자의 인증 상태를 서버에 저장하고, 그 상태
udangtang-dev.tistory.com
이번에는 스프링 시큐리티를 사용해보고자 한다.
Spring Security는 Spring Framework의 강력한 보안 모듈로, 애플리케이션의 인증과 권한 부여를 관리한다.
기본적으로 사용자 정의가 가능한 보안 정책을 제공해서, 폼 로그인이나 OAuth2, JWT등은 쉽게 구현 가능하다. !
기본적인 흐름은 다음과 같다 ( 세션과 유사 )
- 로그인 요청:
사용자가 브라우저에서 사용자 이름과 비밀번호를 입력하여 로그인 요청을 보냅니다. - 스프링 시큐리티 필터:
요청은 스프링 시큐리티의 필터 체인을 거칩니다. 이 과정에서 요청이 인증되었는지 확인합니다. - 인증 처리:
스프링 시큐리티가 설정한 UserDetailsService(사용자가 작성한 파일입니다.)를 통해 사용자의 정보를 로드하고, AuthenticationManager(이 또한 임의로 작성한 파일입니다.)가 사용자의 비밀번호를 검증합니다. - 인증 성공/실패 처리:
인증에 성공하면 사용자는 인증된 상태로 애플리케이션에 접근할 수 있으며, 인증 실패 시 로그인 페이지로 리다이렉트됩니다. - 세션 관리:
스프링 시큐리티는 세션을 관리하여 사용자의 인증 상태를 유지합니다.
프로젝트 셋업
Maven 또는 Gradle을 사용해 스프링 부트 프로젝트를 설정하고, spring-boot-starter-security를 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId> <!-- Thymeleaf를 로그인 폼에 사용 -->
</dependency>
기본적인 시큐리티 설정
스프링 시큐리티의 기본 설정을 통해 인증 및 인가를 처리할 수 있다. 기본적으로 UserDetailsService를 구현하여 사용자 인증 정보를 관리하도록 하겠다...!
// import 문들은 생략..
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/public/**").permitAll() // 로그인 페이지와 공용 자원은 모두 접근 가능
.anyRequest().authenticated() // 그 외 요청은 인증 필요
.and()
.formLogin()
.loginPage("/login") // 커스텀 로그인 페이지
.defaultSuccessUrl("/dashboard", true) // 로그인 성공 시 대시보드로 이동
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll();
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
var user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
조금 더 부가 설명을 하자면, 다음과 같다.
- authorizeRequests(): 각 경로에 대한 접근 권한을 설정합니다. 예를 들어, /login 페이지는 누구나 접근할 수 있도록 설정하고, 다른 모든 요청은 인증된 사용자만 접근할 수 있도록 합니다.
- formLogin(): 스프링 시큐리티가 기본으로 제공하는 로그인 폼을 사용할지 커스텀할지를 설정합니다. 여기서는 /login 페이지를 커스텀 페이지로 지정했습니다.
- logout(): 로그아웃 처리를 위한 설정입니다. 로그아웃 성공 시 리다이렉트할 경로를 설정할 수 있습니다.
- InMemoryUserDetailsManager: 간단한 예시로, 메모리 내에서 사용자 정보를 저장하여 인증합니다. 실제 애플리케이션에서는 데이터베이스 연동을 사용합니다.
로그인 페이지 HTML ( Thymeleaf 페이지 생성 )
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<form th:action="@{/login}" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username"/>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password"/>
</div>
<div>
<button type="submit">Login</button>
</div>
</form>
<div th:if="${param.error}"> // 로그인 에러 시, error로 넘어오게 처리
<p>Invalid username or password</p>
</div>
<div th:if="${param.logout}"> // 로그아웃 하면, logout으로 넘어오게 처리.
<p>You have been logged out</p>
</div>
</body>
</html>
로그인 성공 시 처리 할페이지 ( 대시보드 )
// import 문 생략
@Controller
public class DashboardController {
@GetMapping("/dashboard")
public String dashboard(Model model, Authentication authentication) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
model.addAttribute("username", userDetails.getUsername());
return "dashboard";
}
}
대시보드 HTML
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Dashboard</title>
</head>
<body>
<h2>Welcome, <span th:text="${username}">User</span>!</h2>
<a th:href="@{/logout}">Logout</a>
</body>
</html>
CustomUserDetailsService
//import 생략
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return org.springframework.security.core.userdetails.User
.withUsername(user.getUsername())
.password(user.getPassword())
.roles(user.getRole())
.build();
}
}
장단점
장짐
• 강력한 보안: 다양한 보안 설정과 인증, 권한 관리를 손쉽게 설정 가능
• 유연성: 폼 로그인, 세션 기반 인증, OAuth2, JWT 등의 다양한 인증 방식을 위해 사용자 정의 가능
단점
• 복잡성: 세션에 비해서 설정이 복잡하다.
• 기본 제공 기능의 제한: 간단한 프로젝트에서는 과도할 수 있다.
'Java' 카테고리의 다른 글
[ Java ] 자바에서 구현 해볼 수 있는 로그인 기법-3 ( JWT 로그인 기법 ) (0) | 2024.10.29 |
---|---|
[ Java ] 자바에서 구현 해볼 수 있는 로그인 기법-1 ( 세션 기반 로그인 ) (0) | 2024.09.26 |