[Spring Boot] Spring Security (1) - 기본 프로젝트 생성
개발환경
- Eclipse IDE 2022-06
- Spring Boot 2.7.2
- Gradle 7.0
- Lombok
- PostgreSQL
Spring Security는 Spring Boot의 하위 프레임 워크이며 Java 어플리케이션에 인증과 권한 부여를 제공하는데 중점을 둔 프레임워크이다. Spring에서는 사실상 Spring Security를 표준으로 하여 보안기능을 제공하며 필터기반으로 처리한다. 사용자의 ID와 PASSWORD를 입력받아 인증을 하고 역할 및 권한을 부여할 수 있으며 CSRF(Cross Stie Script Forgery) 같은 취약점에도 대응이 가능하다. 우선 샘플 프로젝트를 생성하여 얕은 지식과 기능을 하나하나 채워가보도록 하자.
- build.gradle
plugins { id 'org.springframework.boot' version '2.7.2' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id 'war' } group = 'com.lombok' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' } tasks.named('test') { useJUnitPlatform() }
http://localhost:8080/login
프로젝트 생성 후 서버를 구동해서 들어가면 필자가 만들어 놓은 페이지는 없지만 위 사진과 같이 Spring Security에서 제공하는 Login 페이지가 나온다. Spring Security는 설정을 하지 않으면 기본적으로 모든 페이지에 권한을 체크한다. 지금부터 웹 페이지에 접속하면 방문자나 회원이 들어갈 수 있는 홈 화면, 로그인 화면, 회원만 들어갈 수 있는 화면 이렇게 세가지의 화면을 만들어보자.
- application.properties
# Thymeleaf 템플릿 연결 spring.thymeleaf.cache=false spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html
- SecurityConfiguration.java
package com.example.security; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @EnableWebSecurity public class SecurityConfiguration { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { /* @formatter:off */ http .authorizeRequests() .antMatchers("/", "/home").permitAll() // 설정한 리소스의 접근을 인증절차 없이 허용 .anyRequest().authenticated() // 그 외 모든 리소스를 의미하며 인증 필요 .and() .formLogin() .loginPage("/login") // 기본 로그인 페이지 .permitAll() .and() .logout() .permitAll(); return http.build(); /* @formatter:on */ } @Bean public UserDetailsService userDetailsService() { /* @formatter:off */ UserDetails user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build(); /* @formatter:on */ return new InMemoryUserDetailsManager(user); // 메모리에 사용자 정보를 담는다. } }
User 클래스의 withDefaultPasswordEncoder 메소드는 Deprecated 되어 있으며 실제 운영서버에서는 사용하지 말아야 한다. 샘플코드에서만 다루고 다음 시간부터는 사용하지 않을 예정이다.
- HomeController.java
package com.example.security.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HomeController { @GetMapping({ "/", "/home" }) public String home() { return "home"; } @GetMapping("/login") public String login() { return "login"; } @GetMapping("/hello") public String hello() { return "hello"; } }
- home.html
<!DOCTYPE html> <html xmlns:th="https://www.thymeleaf.org"> <head> <title>Spring Security Example</title> </head> <body> <h1>Welcome!</h1> <p> Click <a th:href="@{/hello}">here</a> to see a greeting. </p> </body> </html>
- login.html
<!DOCTYPE html> <html xmlns:th="https://www.thymeleaf.org"> <head> <title>Spring Security Example</title> </head> <body> <h1>Spring Security Login page</h1> <div th:if="${param.error}">Invalid username and password.</div> <div th:if="${param.logout}">You have been logged out.</div> <form th:action="@{/login}" method="post"> <div> <label> User Name : <input type="text" name="username" /></label> </div> <br> <div> <label> Password : <input type="password" name="password" /></label> </div> <br> <div> <input type="submit" value="Sign In" /> </div> </form> </body> </html>
- hello.html
<!DOCTYPE html> <html xmlns:th="https://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> <head> <title>Hello World!</title> </head> <body> <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1> <form th:action="@{/logout}" method="post"> <input type="submit" value="Sign Out" /> </form> </body> </html>
- 사용자 화면 테스트
SecurityConfiguration.java에서 설정하였던 사용자 정보를 입력하자. user / password
이렇게 기본적으로 Spring Security를 이용한 기본적인 페이지를 완성해보았다. 사용자는 홈화면에 접속하고 로그인을 하여 사용자 전용 페이지에 접근하는 시나리오이다. 다음 시간에는 데이터베이스로부터 사용자 정보를 가져와 로그인 인증을 해야겠다.
다음글 : [Spring Boot] Spring Security (2) - 회원가입 및 로그인 With PostgreSQL
'Programming > Spring Security' 카테고리의 다른 글
[Spring Boot] Spring Security (5) - 역할(hasRole)과 권한(hasAuthority)의 차이는 무엇일까? (0) | 2022.08.22 |
---|---|
[Spring Boot] Spring Security (4) - 역할 별 페이지 접근제어 (0) | 2022.08.19 |
[Spring Boot] Spring Security (3) - 로그인 시 사용자 역할 조회 및 부여 (0) | 2022.08.17 |
[Spring Boot] Spring Security (2) - 회원가입 및 로그인을 위한 데이터베이스 연동 (0) | 2022.08.16 |
댓글