[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 |
댓글