1. 프로젝트 생성

1) 프로젝트 설정
✔ bulid.gradle

// jsp 설정 추가
eclipse.wtp.facet {
// Change the version of the Dynamic Web Module facet
facet name: 'jst.web', version: '5.0'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
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'
// 추가
implementation 'jakarta.servlet:jakarta.servlet-api'
implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api'
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
}
✔application.properties
server.port=8081
# JSP 설정
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
2) jsp 파일 생성을 위한 폴더 구성

2. 코드작성
1) Controller
- [com.study.springboot] 패키지에 MyController 생성
@Controller
public class MyController {
@RequestMapping("/")
public @ResponseBody String root() {
return "security";
}
@RequestMapping("/guest/welcome")
public String welcome1() {
return "guest/welcome1";
}
@RequestMapping("/member/welcome")
public String welcome2() {
return "member/welcome2";
}
@RequestMapping("/admin/welcome")
public String welcome3() {
return "admin/welcome3";
}
}
- 위 컨트롤러에 맞게 jsp파일 생성

2) SecurityConfig
- [com.study.springboot.auth] 패키지 생성하여 WebSecurityConfig 생성
: SecurityFilterChain과 UserDetailsService를 빈으로 등록하기
package com.study.springboot.auth;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import jakarta.servlet.DispatcherType;
@Configuration
public class WebSecurityConfig {
// 두가지 빈을 등록해서 사용
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf((csrf) -> csrf.disable())
.cors((cors) -> cors.disable())
.authorizeHttpRequests(request -> request
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
.requestMatchers("/").permitAll()
.requestMatchers("/css/**", "/js/**", "/img/**").permitAll()
.requestMatchers("/guest/**").permitAll()
.requestMatchers("/member/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated() // 어떠한 요청이라도 인증 필요
);
http.formLogin().permitAll(); // 기본 로그인 페이지
http.logout().permitAll(); // 로그아웃 기본설정
return http.build();
}
@Bean
public UserDetailsService userService() {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("1234"))
.roles("USER") // ROLE_USER 에서 ROLE_은 자동으로 붙음
.build();
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("1234"))
.roles("USER","ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
private PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
3. 💻 구동 확인

1) 비로그인 (guest) 상태

2) user로 로그인(member)

3) admin으로 로그인

4. 커스텀 화면 적용하기
Security의 기본 로그인 폼을 사용하지않고 직접 jsp파일을 커스텀하여 적용해보자.
1) jsp 파일 추가
페이지 변경되는 것을 확인하기 위해 별다른 스타일 적용 없이 간단하게만 작성했다.

2) Controller
loginError.jsp, loginForm.jsp에 대한 각각의 매핑 추가하기
@RequestMapping("/loginForm")
public String loginForm() {
return "security/loginForm";
}
@RequestMapping("/loginError")
public String loginError() {
return "security/loginError";
}
3) WebSecurityConfig 수정
filterChain() 내부의 http.formLogin, http.logout을 기본설정에서 커스텀한 페이지로 변경하여 적용한다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf((csrf) -> csrf.disable())
.cors((cors) -> cors.disable())
.authorizeHttpRequests(request -> request
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
.requestMatchers("/").permitAll()
.requestMatchers("/css/**", "/js/**", "/img/**").permitAll()
.requestMatchers("/guest/**").permitAll()
.requestMatchers("/member/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated() // 어떠한 요청이라도 인증 필요
);
// http.formLogin().permitAll(); // 기본 로그인 페이지
// http.logout().permitAll(); // 로그아웃 기본설정
http.formLogin((formLogin) -> formLogin
.loginPage("/loginForm")
.loginProcessingUrl("/j_spring_security_check")
.failureUrl("/loginError")
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll()
);
http.logout((logout) -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll()
);
return http.build();
}
💻 구동 확인

변경된 로그인 화면과 로그인 실패시 에러페이지로 이동하는 것을 확인할 수 있다.
member와 admin 페이지의 정상/비정상 접근 처리는 동일하게 적용된다.
'Framework > SpringBoot' 카테고리의 다른 글
| [Spring Boot] Security Database 사용하기 (1) | 2023.11.22 |
|---|---|
| [Spring Boot] ①Security Status Check , ②Security taglib 사용하기 (1) | 2023.11.22 |
| [Spring Boot] Transaction 적용하기 (2) | 2023.11.20 |
| [Spring Boot] Service를 적용하여 비즈니스 로직 수행하기 (1) | 2023.11.20 |
| [Spring Boot] WebJars에서 bootstrap 적용하기 (0) | 2023.11.16 |