스프링 시큐리티 2-1 (pom.xml) 분석
pom.xml
스프링 시큐리티 2
hibernate.dialect 설정
mariandb 로 세팅
JPA에서 말하는 Dialect(방언)이란?
- JPA에선 설정을 통해 원하는 Dialect만 설정해주면 해당 Dialect를 참고하여 그에 맞는 쿼리를 생성한다.실제 고객의 환경이 SQL SERVER를 사용 중이라면
- 설정만 SQLServerDialect로 변경해주면 된다.
- 따라서 개발 시에는 Oracle DB에 맞게 설정하고 어플리케이션을 개발하다
스프링 Intellij - 실시간 반영하기(코드 자동 재시작)
spring-boot-devtools를 사용하여 소스코드 자동반영 설정하기 (intelliJ)
[maven의 경우]
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
2. IntelliJ 세팅해주기
(1) File > Settings 메뉴 혹은 ctrl + shift + s 단축키를 눌러서 Settings 으로 들어간다.
Advanced Settings 메뉴에서
[Allow auto-make to start even if developed application is currently running] 를 클릭해준다.
(2) Build,Execution,Deployment > Compiler 탭에서
[Build project automatically]를 체크해준다.
여기까지 하면 변경사항이 있을 때 새로고침 하면 자동으로 반영이 된다.
http.formLogin(
httpSecurityFormLoginConfigurer -> {
httpSecurityFormLoginConfigurer
.loginPage("/login")
.loginProcessingUrl("/loginProc")
.defaultSuccessUrl("/")
.failureUrl("/failed")
.usernameParameter("username")
.passwordParameter("password")
.failureHandler((request, response, exception) -> {
System.out.println("실패 핸들러");
})
.successHandler((request, response, authentication) -> {
System.out.println("성공 핸들러");
System.out.println("getDetails :"+authentication.getDetails());
System.out.println("getPrincipal : "+authentication.getPrincipal());
}).permitAll() //로그인 페이지 및 로그인 처리 URL에 대한 접근을 모든 사용자에게 허용합니다.
;
}
);
defaultSuccessUrl 은 로그인 성공 후에 이동할 경로를 정해주는 것은 맞지만 우선순위는 가장 마지막입니다.
강의 중에 SavedRequest 와 RequestCache 와 관련된 내용이 나오는데 스프링 시큐리티는 기본적으로
로그인을 성공하게 되면 제일 먼저 로그인을 성공하기 직전에 거쳐왔던 Url 정보를 기억하고 있다가 성공하게 되면 그 Url로 리다이렉트 합니다.
2번째
defaultSuccessUrl 보다 더 우선적으로 SavedRequest 와 RequestCache 를 사용해서 나온 경로를 먼저 참조하고 만약 값이 없을 경우 그 다음에 request.getParameter("경로") 의 값이 있는지 확인하고 이 외에도 우선순위에 따라 targetUrl 을 계속 구하다가 아무런 값도 못 얻었을 경우 defaultSuccessUrl 에서 설정한 경로를 참조해서 리다이렉트 합니다.
3.
보통 기본 값이라는 것은 특별한 설정을 하지 않을 경우 오류가 나거나 null 값을 가지지 않도록 하기 위한 목적으로 사용하기 때문에 특별한 이유가 없으면 SuccessHandler 를 사용해서 직접 리다이렉트 하는 방식으로 하면 좋을 것 같습니다.
gpt 질문? loginProcessingUrl 설명해줘
Spring Security의 loginProcessingUrl은 애플리케이션에서 로그인 요청을 처리할 URL 경로를 설정하는 데 사용됩니다. 이 URL은 클라이언트(예: 브라우저)가 로그인 정보를 제출할 때 사용하는 경로입니다. loginProcessingUrl은 기본적으로 Spring Security가 인증 요청을 처리하는 경로를 정의하며, 인증 로직을 수행하기 위해 설정됩니다.
기본 동작
Spring Security를 사용할 때, 기본적으로 로그인 요청의 경로는 /login으로 설정되어 있습니다. 클라이언트가 POST 요청을 해당 경로로 전송하면 Spring Security는 로그인 요청을 처리하고 사용자를 인증합니다.
위 설정에서 loginProcessingUrl을 /perform_login으로 지정하면, 클라이언트는 이제 /perform_login 경로로 로그인 요청을 보내야 합니다.
주요 특징
- POST 요청만 처리
loginProcessingUrl로 설정된 URL은 POST 요청만 처리합니다. GET 요청은 무시되며 405(Method Not Allowed) 응답이 반환될 수 있습니다. - 자동 인증 처리
설정된 URL로 로그인 데이터를 전송하면 Spring Security가 내부적으로 인증 처리를 수행합니다. 기본적으로 다음과 같은 파라미터가 필요합니다:- username: 사용자 이름
- password: 비밀번호
- 커스텀 경로 설정
기본 경로(/login) 대신 애플리케이션 요구사항에 맞는 URL로 변경할 수 있습니다. - 보안 필터와의 연동
loginProcessingUrl은 Spring Security의 UsernamePasswordAuthenticationFilter에 의해 처리됩니다.
예제
1. 기본 설정
클라이언트는 다음과 같이 요청을 보냅니다:
2. 커스텀 설정
이 경우 클라이언트는 /auth/login로 요청해야 하며, 파라미터 이름은 email과 pass를 사용합니다:
주의사항
- loginProcessingUrl은 클라이언트가 정확한 경로로 요청을 보낼 때만 작동합니다.
- POST 요청 외의 요청을 보내면 에러가 발생합니다.
- 사용자 정의 로직이 필요할 경우, 별도의 AuthenticationFilter를 구현하거나 설정을 확장해야 할 수 있습니다.
요약
loginProcessingUrl은 Spring Security의 인증 흐름에서 로그인 요청을 처리할 경로를 정의하며, 클라이언트가 인증 데이터를 제출할 때 사용하는 URL입니다. 애플리케이션의 보안 요구 사항에 따라 이 경로를 커스터마이징할 수 있습니다.
.loginProcessingUrl("/loginProc") 은 html 에 action 값과 동일하게 세팅한다.
로그 설정
○ logback-spring.xml configuration 구성
logback-spring.xml은 크게 appender와 logger, root로 구성됩니다.
- logger : <logger> 테그로 로그의 name 속성을 통해 class 별로 지역설정을 할 수 있으며 additivity 속성을 통해 log level을 상속 유무 설정이 가능합니다.
- root : <root> 테그로 구성되며 logger 중에 전역 logger를 root로 따로 분리했다고 보시면 됩니다. 전역 설정이기때문에 name 속성이 없으며 level 속성을 통해 log level만 지정해주면 됩니다.
- 기본
- appender : <appender> 테그로 구성되며 log 메시지가 출력될 대상을 결정
- ch.qos.logback.core.ConsoleAppender : 콘솔에 로그를 찍음, 로그를 OutputStream에 작성하여 콘솔에 출력되도록 한다.
- ch.qos.logback.core.FileAppender : 파일에 로그를 찍음, 최대 보관 일 수 등를 지정할 수 있다.
- ch.qos.logback.core.rolling.RollingFileAppender : 여러개의 파일을 롤링, 순회하면서 로그를 찍는다.(FileAppender를 상속 받는다. 지정 용량이 넘어간 Log File을 넘버링 하여 나누어 저장할 수 있다.)
- ch.qos.logback.classic.net.SMTPAppender : 로그를 메일에 찍어 보낸다.
- ch.qos.logback.classic.db.DBAppender : DB(데이터베이스)에 로그를 찍는다.
가장 많이 사용되는 appender 속성은 ConsoleAppender와 RollingFileAppender 입니다. 본 글에서도 두 appeder를 만들어 보도록 하겠습니다.
○ ConsoleAppender 만들기
먼저 ConsoleAppender 를 전체 설정을 보도록 하겠습니다.
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<property name="CONSOLE_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %magenta([%thread]) %highlight([%-3level]) %logger{5} - %msg %n" />
<!-- Console appender 설정 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>${CONSOLE_PATTERN}</Pattern>
</encoder>
</appender>
<logger name="jdbc" level="OFF" additive="false">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="jdbc.sqlonly" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
</logger>
<logger name="jdbc.sqltiming" level="OFF" additive="false" >
<appender-ref ref="STDOUT"/>
</logger>
<logger name="org.hibernate.SQL" level="DEBUG" additive="false">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="com.example.todolist.controller" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
</logger>
<logger name="com.example.todolist.service" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
</logger>
<logger name="com.example.todolist.domain" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
</logger>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
property 옵션의 경우 설정 파일에서 사용될 상수 변수라고 보시면 됩니다.
ConsoleAppender에서 로그 형식을 지정해준 뒤 콘솔에 찍고 싶은 logger에 appender를 추가해줬습니다. <appender> 하위의 encoder는 Appender에 포함되어 사용자가 지정한 형식으로 표현 될 로그메시지를 변환하는 역할을 담당하는 요소입니다.
pattern layout에 대한 설정은 https://logback.qos.ch/manual/layouts.html 참고 바랍니다.
○ <Logger> 속성
간단하게 logger의 level 속성 테스트를 진행해보겠습니다.
<logger name="com.example.todolist.controller" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
</logger>
위 로거는 controller 하위에 있는 파일에 로그 레벨을 DEBUG로 설정되어 있습니다.
테스트 controller를 만들어 보겠습니다.
@Slf4j
@Controller
public class IndexController {
@GetMapping("/")
public String index(){
log.trace("TRACE!!");
log.debug("DEBUG!!");
log.info("INFO!!");
log.warn("WARN!!");
log.error("ERROR!!");
return "index";
}
}
그리고 해당 url을 호출하면 INFO보다 INFO를 포함한 상위 Log level만 console에 찍히는 것을 알 수 있습니다.
이와같이 log level을 이용하여 Log를 좀 더 효율적으로 관리할 수 있습니다.
이번엔 logger의 additive 속성 테스트를 진행해보겠습니다.
<logger name="com.example.todolist.controller" level="DEBUG" additive="true" >
<appender-ref ref="STDOUT"/>
</logger>
이제 다시 결과를 확인해보면 INFO 로그도 찍히는 것을 확인할 수 있습니다.
additive 란 상위 logger로부터 상속 여부를 의미합니다(기본 값 true). true로 설정되며 상위 logger의 설정 값을 상속 받아 자신의 logger에 설정된 값을 재적용 시키며, false일 경우 상속을 받지 않고 자신의 설정 값을 사용합니다.
여기선 root의 값을 상속받아 INFO level이 적용된 것을 볼 수 있습니다.
○ RollingFileAppender 추가하기
이번에도 RollingFileAppender를 위에서 만든 ConsoleAppender 설정에 추가한 전체 설정을 보도록 하겠습니다.
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<property name="CONSOLE_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %magenta([%thread]) %highlight([%-3level]) %logger{5} - %msg %n" />
<property name="ROLLING_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %logger{5} - %msg %n" />
<property name="FILE_NAME" value="D:\\logs\\application.log" />
<property name="LOG_NAME_PATTERN" value="./logs/application-%d{yyyy-MM-dd-HH-mm}.%i.log" />
<property name="MAX_FILE_SIZE" value="10MB" />
<property name="TOTAL_SIZE" value="30MB" />
<property name="MAX_HISTORY" value="2" />
<!-- Console appender 설정 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>${CONSOLE_PATTERN}</Pattern>
</encoder>
</appender>
<appender name="ROLLING_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${ROLLING_PATTERN}</pattern>
</encoder>
<file>${FILE_NAME}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_NAME_PATTERN}</fileNamePattern>
<maxHistory>${MAX_HISTORY}</maxHistory>
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<totalSizeCap>${TOTAL_SIZE}</totalSizeCap>
</rollingPolicy>
</appender>
<logger name="jdbc" level="OFF" additive="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</logger>
<logger name="jdbc.sqlonly" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</logger>
<logger name="jdbc.sqltiming" level="OFF" additive="false" >
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</logger>
<logger name="org.hibernate.SQL" level="DEBUG" additive="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</logger>
<logger name="com.example.todolist.controller" level="INFO" additive="true" >
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</logger>
<logger name="com.example.todolist.service" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</logger>
<logger name="com.example.todolist.domain" level="DEBUG" additive="false" >
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</logger>
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_LOG_FILE"/>
</root>
</configuration>
RollingFileAppender는 FileAppender를 상속하여 로그 파일을 rollover 합니다. 여기서 rollover는 타깃 파일을 바꾸는 것으로 이해할 수 있습니다.
RollingFileAppender의 요소로 file과 rollingPolicy가 보입니다. 먼저 File 요소를 통해 log파일의 이름을 설정할 있습니다. 그리고 rollingPolicy를 설정해 rollover를 어떻게 실행할지를 정의합니다.
rollingPolicy에도 여러 종류가 있다. 몇가지만 살펴보면
- TimeBasedRollingPolicy: 이름에서 알 수 있듯이 시간에 기반하여 rollover 정책을 정의할 수 있다.
- SizeAndTimeBasedRollingPolicy: TimeBasedRollingPolicy 상속받아 maxFileSize 을 통해 파일의 크기까지 고려할 수 있다.
- FixedWindowRollingPolicy : Fixed Window 알고리즘에 따라 로그 파일의 이름을 지정
이 중에서도 우린 가장 많이 사용하는 TimeBasedRollingPolicy를 상속받아 만들어진 SizeAndTimeBasedRollingPolicy을 사용하였습니다.
rollingPolicy 하위 요소를 살펴보면
- fileNamePattern : 아카이브 되는 파일의 패턴을 지정할 수 있다.
- maxHistory : 보관할 최대 파일 수를 제어하여 이전 파일을 삭제한다.
- maxFileSize : 분할할 용량 사이즈를 의미한다.
- totalSizeCap : 전체 파일 크기를 제어하며, 전체 크기 제한을 초과하면 가장 오래된 파일을 삭제한다.
totalSizeCap을 사용하기 위해서는 maxHistory 속성이 필수이며, maxHistory와 totalSizeCap의 우선순위는 maxHistory가 더 높다.
이제 테스트를 위해 어플리케이션을 간단히 조작한 뒤 지정한 경로를 확인해보면 log 파일이 생성된 것을 확인할 수 있습니다.
아카이브 되는 파일의 시간 기준은 fileNamePattern에 설정한 로그 시간 기준입니다. fileNamePattern에서 분으로 해놓았기 때문에 16분에 다시 확인해보면 아카이브 파일도 확인할 수 있습니다.
17분에 다시 확인하면 아카이브 파일이 하나 더 생성된 것을 확인할 수 있습니다.
18분에 다시 확인하면 아카이브 파일이 2개에서 늘어나진 않고 16분 17분에 만든 파일만 남아 있는 것을 볼 수 있습니다. 이는 maxHistory를 2로 설정해두었기 때문입니다.
'Spring Security' 카테고리의 다른 글
2일차, 스프링 시큐리티 1 (2) | 2025.01.08 |
---|---|
3일차,스프링 시큐리티 2 (1) | 2025.01.08 |
1일차, 스프링 부트 환경세팅, Docker MarinaDB 설치 (1) | 2024.12.28 |