스프링 시큐리티

Spring Security는 Java 애플리케이션을 위한 보안 프레임워크로, 인증(authentication)과 인가(authorization)를 유연하고 확장 가능하게 지원합니다. Spring Boot에서는 spring-boot-starter-security 스타터를 통해 관련 의존성을 한 번에 관리하고 자동 구성을 제공합니다.
<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>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>spring-boot-starter-security는 Spring Security 관련 의존성을 묶어 제공하며, 기본적인 보안 필터 체인을 자동 구성합니다./css/**, /js/**, /images/** 등 정적 리소스 경로는 인증 없이 접근할 수 있도록 기본 제외됩니다.application.properties에서 기본 사용자 계정과 역할을 변경할 수 있습니다:
spring.security.user.name=alice
spring.security.user.password=alicepw
spring.security.user.roles=USER,ADMIN템플릿을 렌더링하기 위한 컨트롤러 없이도 뷰 연결을 할 수 있습니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
@Bean
public SpringSecurityDialect securityDialect() {
return new
필요에 따라 명시적 컨트롤러를 정의할 수도 있습니다:
@Controller
public class HomeController {
@GetMapping("/")
public ModelAndView home() {
return new ModelAndView("home");
}
}thymeleaf-extras-springsecurity6 의존성을 추가하고, 뷰에서 sec:authorize 등의 속성을 사용할 수 있습니다.
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency><!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/extras/spring-security">
<head>
<title>Spring Security 튜토리얼</title>
</head>
<body>
<h2>Welcome</h2>
<div sec:authorize="
@Entity
@Table(name = "users")
public class User {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false, unique = true)
private
@Entity
@Table(name = "roles")
public class Role {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false, unique = true)
private
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByEmail(String email);
}
public interface RoleRepository extends JpaRepository<Role, Integer> {
Optional<Role> findByRolename(String rolename);
}UserDetailsService를 구현하여 DB에서 사용자 정보를 로드합니다.
@Service
@Transactional
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userRepository.findByEmail(username)
.orElseThrow(()
@Configuration
public class WebSecurityConfig {
@Autowired
private UserDetailsService customUserDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration config) throws Exception {
return config
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}BCrypt는 자동으로 랜덤 솔트를 생성하여 같은 평문이라도 매번 다른 해시를 생성합니다.
th:action과 POST/PUT/DELETE 메서드를 사용하면 CSRF 토큰이 자동 삽입됩니다.http.csrf(csrf -> csrf.disable());<form th:action="@{/signup}" th:object="${user}" method="post">
<div th:if="${emailExists}">
<span style="color:red">Email already exists</span>
</div>
<label>Email:</label