728x90
🛠️ 초기 세팅



📘 1. MemberController.java
@Controller
public class MemberController {
@GetMapping("/signup")
public String showSignupForm() {
return "signup";
}
@GetMapping("/signin")
public String showSigninForm() {
return "signin";
}
}
✅ 설명
- @Controller: 이 클래스가 Spring MVC의 컨트롤러임을 나타냄. 요청을 처리하고 뷰(View)를 반환하는 역할을 한다.
- @GetMapping("/signup"): /signup 주소로 GET 요청이 들어오면 signup.html을 반환한다. 즉, 회원가입 화면을 보여주는 역할.
- @GetMapping("/signin"): /signin 주소로 GET 요청이 들어오면 signin.html을 반환. 즉, 로그인 화면을 보여주는 역할.
✏️ 주석으로 쓰자면:
// 회원가입 화면 요청 처리
// GET /signup 요청 시 signup.html 반환
📘 2. SecurityConfig.java
package io.shi.sec_form.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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;
//public class SecurityConfig extends WebSecurityConfiguration { 이건 옛날 방식이니까 사용하지 마삼 빈 사용해
@Slf4j
@Configuration
public class SecurityConfig {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// @Bean
// public PasswordEncoder passwordEncoder() {
// return PasswordEncoderFactories.createDelegatingPasswordEncoder();
// }
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//여기에 설정을 하나씩 넣어줘야됨
return http
.csrf(csrf -> csrf.disable() )
// .formLogin(
// form -> {
// form.failureForwardUrl("/login?error=true")
// //.successForwardUrl("/index") //로그인에 성공하면 페이지는 그대로 둠
// //.defaultSuccessUrl("/happy")
// .usernameParameter("loginId")
// .passwordParameter("loginPwd")
// .loginProcessingUrl("/signin")
// .loginPage("/signin")
// .permitAll();
// }
// )
.formLogin(Customizer.withDefaults())
// .logout(Customizer.withDefaults())
.logout( logout -> {
logout.logoutUrl("/signout")
.logoutSuccessUrl("/")
.clearAuthentication(true)
.invalidateHttpSession(true) //우리 서버에서 갖고있는 httpsession을 무효화 시키겠다
.deleteCookies("JSESSIONID");
})
.authorizeHttpRequests(
auth -> {
auth.requestMatchers("/signup", "/signin")
.anonymous()
.requestMatchers("/user/**")
.hasRole("MEMBER")//hasRole로 권한검사를 할 수 있다, 이걸 가지고 있어야 인가를 가질 수 있음
.anyRequest()
//.denyAll(); //아예 접근 못하게 막고 싶을때 사용
.authenticated();
}
)
.build();
}
//인가
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
String targetPwd = "1234";
String encoded = passwordEncoder().encode(targetPwd);
log.info("encoded = {}", encoded);
//얘는 InMemoryUserDetailsManager 객체를 user을만들어줌
manager.createUser(
User.withUsername("user")
.password(encoded)
//.roles()
.build()
);
return manager;
}
}
@Configuration
@Slf4j
public class SecurityConfig {
- @Configuration: 이 클래스는 Spring 설정 클래스임을 의미.
- @Slf4j: 로그를 출력할 수 있도록 도와주는 Lombok 애노테이션.
🔐 PasswordEncoder 설정
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
- 비밀번호를 암호화할 때 사용하는 인코더. 실제 로그인 시 사용자의 비밀번호와 저장된 암호화된 비밀번호를 비교함.
- Spring Security에서 가장 많이 사용하는 방식이 BCrypt.
(보안성이 높고 내부적으로 솔팅(salting)과 반복 해시를 지원) - Spring Security는 로그인 시 사용자가 입력한 비밀번호를 DB에 저장된 암호화된 비밀번호와 비교하는데, 이때 이 BCryptPasswordEncoder가 필요함.
- 로그인 검증 시 자동으로 사용됨.
✅ 주석 처리된 코드와 비교
//@Bean
//public PasswordEncoder passwordEncoder() {
// return PasswordEncoderFactories.createDelegatingPasswordEncoder();
//}
이건 BCrypt뿐 아니라 다양한 암호화 알고리즘을 함께 지원하는 인코더야.
예를 들어, bcrypt, pbkdf2, scrypt, argon2 등을 사용할 수 있도록 내부에서 선택해줘.
📌 보안적으로는 이 방법이 더 유연하지만, 지금처럼 간단한 예제에서는 new BCryptPasswordEncoder()로 충분함.
🔐 SecurityFilterChain 설정
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
- Spring Security의 필터 체인을 설정하는 메서드. 이 메서드 내에서 인증, 인가, 로그인/로그아웃 설정을 모두 할 수 있음.
- Spring Security의 필터 체인을 커스터마이징함
- 필터란 사용자의 요청을 가로채서 인증, 인가 여부를 판단하고, 그 결과에 따라 요청을 진행시킬지 차단할지 결정하는 역할이다.
.csrf(csrf -> csrf.disable())
- CSRF(Cross Site Request Forgery) 공격 방지를 위한 설정. 현재는 개발 편의상 꺼둠.
- CSRF (Cross-Site Request Forgery): 사용자가 인증된 상태에서 악성 요청을 보내는 공격.
- 기본적으로 form POST 요청은 CSRF 토큰이 없으면 거절되는데, 지금은 로그인 화면 만들기 편하게 비활성화한 상태.
- 추후에는 반드시 활성화하고, <input type="hidden" name="_csrf" ...>로 토큰을 포함해줘야 한다.
🔓 로그인 설정
.formLogin(Customizer.withDefaults())
- 기본 로그인 설정을 사용. Spring Security가 제공하는 기본 로그인 화면을 사용함.
- 만약 커스터마이징을 하고 싶다면 .formLogin(form -> { ... }) 방식으로 세부 설정 가능.
- 이건 Spring Security 기본 제공 로그인 화면을 사용하는 설정이야. 즉, /login으로 POST 요청하면 로그인 동작함
💬 주석 처리된 formLogin 설정
//.formLogin(
// form -> {
// form.failureForwardUrl("/login?error=true")
// //.successForwardUrl("/index")
// //.defaultSuccessUrl("/happy")
// .usernameParameter("loginId")
// .passwordParameter("loginPwd")
// .loginProcessingUrl("/signin")
// .loginPage("/signin")
// .permitAll();
// }
//)
(지금은 주석 처리돼 있지만 예전 설정에서는 usernameParameter, passwordParameter 등을 설정하려고 했었음.)
✅ 역할 설명
| 설정 | 설명 |
| loginPage("/signin") | 사용자 정의 로그인 페이지 경로 |
| loginProcessingUrl("/signin") | 로그인 요청을 처리할 URL. 로그인 form의 action과 일치해야 함 |
| usernameParameter("loginId") | 로그인 폼에서 아이디 input의 name 속성 지정 |
| passwordParameter("loginPwd") | 비밀번호 input의 name 속성 지정 |
| failureForwardUrl("/login?error=true") | 로그인 실패 시 이동할 URL |
| .permitAll() | 로그인 페이지 자체는 로그인 안 한 사용자도 접근 가능해야 하므로 허용 |
✔ 이 설정을 사용하면 기본 form 대신 내가 따로 만든 signin.html이 로그인 페이지가 됨.
🔐 로그아웃 설정
.logout(logout -> {
logout.logoutUrl("/signout")
.logoutSuccessUrl("/")
.clearAuthentication(true)
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
})
- 로그아웃 요청 URL: /signout
- 로그아웃 성공 시 이동할 URL: /
- 인증 정보 제거: clearAuthentication(true)
- 세션 무효화: invalidateHttpSession(true)
- 쿠키 제거: deleteCookies("JSESSIONID") (로그인 상태 유지하는 세션 쿠키 제거)
| 설정 | 설명 |
| logoutUrl("/signout") | 로그아웃 처리할 URL (GET/POST 모두 가능) |
| logoutSuccessUrl("/") | 로그아웃 후 이동할 URL |
| clearAuthentication(true) | 현재 사용자의 인증 정보 제거 |
| invalidateHttpSession(true) | 세션 무효화 (로그인 상태 삭제) |
| deleteCookies("JSESSIONID") | 세션 쿠키도 브라우저에서 삭제 |
🔐 인가(접근 권한) 설정
.authorizeHttpRequests(auth -> {
auth.requestMatchers("/signup", "/signin")
.anonymous()
- /signup, /signin은 로그인하지 않은 사용자만 접근 가능하게 설정
- 로그인 안 한 사용자만 접근 가능 (로그인된 사용자는 접근 불가)
.requestMatchers("/user/**")
.hasRole("MEMBER")
- /user/** 경로(주소)는 ROLE_MEMBER 권한이 있어야(권한을 가진 사용자만) 접근 가능.
.anyRequest()
.authenticated();
- 그 외 모든 요청은 로그인된 사용자만 접근 가능.
🔐 사용자 정보 등록
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
String targetPwd = "1234";
String encoded = passwordEncoder().encode(targetPwd);
- InMemoryUserDetailsManager는 메모리 기반으로 사용자 정보를 관리하는 구현체.
- 실제 프로젝트에서는 DB와 연동하지만, 지금은 예제를 위해 메모리에서 사용자 등록.
- 메모리 기반 사용자 저장소를 만들고, 1234라는 비밀번호를 암호화해서 사용자 정보 등록.
- 평문 비밀번호 1234를 암호와하고, 로그로 출력해서 확인할 수 있도록 설정
manager.createUser(
User.withUsername("user")
.password(encoded)
//.roles()
.build()
);
return manager;
}
- username: user, password: 1234인 계정을 생성함. (지금은 roles() 주석처리 되어 있어 ROLE이 없어 인가 오류 날 수 있음)
- user라는 username을 갖고, 1234라는 암호화된 비밀번호를 갖는 사용자 생성.
- .roles("MEMBER") 주석이 해제되어야 /user/** 접근이 가능함.
📘 3. 로그인 폼 (signin.html)
<form action="/signin" method="post">
- 로그인 정보를 서버에 보낼 때 POST 방식으로 /signin 경로로 전송함.
- ⚠️ 하지만 현재 SecurityConfig에서는 이 경로가 로그인 처리 URL이 아님. (loginProcessingUrl("/signin")이 주석처리 되어 있어서 /login으로 동작할 수도 있음)
<input type="text" id="loginId" name="loginId">
<input type="password" id="loginPwd" name="loginPwd">
- 이 부분에서 주의할 점은 name 속성임. Spring Security는 기본적으로 name="username"과 name="password"를 요구함.
따라서 이 코드는 현재 로그인 시 정상 동작하지 않을 가능성이 높음.
✅ 해결 방법:
- loginProcessingUrl("/signin"), usernameParameter("loginId"), passwordParameter("loginPwd") 설정 추가
- 또는 input name을 username, password로 변경
📘 4. 회원가입 폼 (signup.html)
<h1>회원가입 페이지</h1>
- 현재는 단순한 HTML 페이지로 기능은 구현되어 있지 않음.
🔍 결론적으로 전체 흐름 요약
- /signin 접속 시 signin.html 반환됨 (로그인 화면)
- 로그인 요청은 /login (기본값), 또는 /signin (커스터마이징 시)
- 로그인 성공 시 기본 페이지로 이동 (설정 변경 가능)
- 로그아웃 시 /로 이동
- /user/**는 MEMBER 권한 필요
- 사용자 정보는 메모리 내에 user/1234 로 존재
- 비밀번호는 BCrypt로 암호화됨
728x90
'프로그래밍 > Spring' 카테고리의 다른 글
| 💭Spring Security OAuth2 로그인 구현 - 4월 15일 (0) | 2025.04.16 |
|---|---|
| JPA 핵심 메서드 정리 (0) | 2025.04.14 |
| entityManager.persist()란? (0) | 2025.04.14 |
| Hibernate실습, JPQL 활용2 - 4월 14일 (0) | 2025.04.14 |
| Hibernate실습, JPQL 활용 - 4월 14일 (0) | 2025.04.14 |