스프링 부트에 템플릿 엔진으로 머스테치를 사용하게 되면, 한글이 깨져나왔다.

위와 같은 환경에서 올바른 한글 출력을 위한 설정은 아래와 같다.

 

application.properties

server.servlet.encoding.force-response=true

 

 

참고문헌

https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html

'Java > SpringBoot' 카테고리의 다른 글

Spring Security CSRF 설정  (0) 2021.12.09
Spring Security 기본 설정  (0) 2021.12.08
Logback 기본 설정  (0) 2021.12.07

CSRF 비활성화

				...
@Override
    public void configure(HttpSecurity http) throws Exception { 
    	http.csrf().disable();
        
    			...

위와같이 스프링에서 csrf를 비활성화하면 스프링 시큐리티는 토큰을 발행하지 않는다.

하지만 보안상으로 좋지 않기때문에 개발과정이 아닌 이상 권장하지 않는다.

 

스프링 시큐리티는 csrf().disable()을 하지 않으면 알아서 csrf보호(토큰 발행,확인)를 하기 때문에

특별히 다른 설정은 안 했다.

 

현재 쓰고있는 템플릿 엔진이 JSP라서 관련해서 찾아보니까 보통 input hidden으로 토큰 값을 보내줬다.

(써보진 않았지만 thymeleaf도 비슷한 방식인 듯 하다.)

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">

위와같이 form 안에 토큰 값을 담아서 보내주니 문제없이 제대로 작동됐다.

 

 

 

참고문헌

Baeldung 'A Guide to CSRF Protection in Spring Security' https://www.baeldung.com/spring-security-csrf

'Java > SpringBoot' 카테고리의 다른 글

Spring boot : Mustache 사용시 한글 인코딩 설정  (0) 2024.03.11
Spring Security 기본 설정  (0) 2021.12.08
Logback 기본 설정  (0) 2021.12.07

1. Spring Security Dependency 추가

 

gradle

dependencies { implementation "org.springframework.boot:spring-boot-starter-security" }

maven

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.6.1</version>
</dependency>

 

 

2. Security패키지를 생성하고, 안에 SecurityConfig클래스를 추가한다.

: SecurityConfig클래스는 WebSecurityConfigureAdapter를 상속받는다.

 

기본 설정이 된 SecurityConfig클래스의 코드는 아래와 같다.

@Configuration // 설정을 위한 어노테이션
@EnableWebSecurity // 스프링 시큐리티 사용을 위한 어노테이션
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Override
    public void configure(HttpSecurity http) throws Exception { // Security 기본 설정
        http.authorizeRequests()
                .antMatchers("/css/**", "/js/**", "/img/**", "/favicon.ico").permitAll() // resource들은 권한 없이 접근 가능하다.
                .antMatchers("/").hasRole("USER")
                .anyRequest().authenticated();

        http.formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/authenticate") // login페이지 form의 action과 값이 같아야한다.
                .usernameParameter("userId")
                .passwordParameter("password")
                .defaultSuccessUrl("/")
                .failureUrl("/login?error")
                .permitAll();

        http.logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login");

        http.sessionManagement()
                .maximumSessions(1)
                .maxSessionsPreventsLogin(false); // 먼저 접속한 사용자를 로그아웃 시킨다.
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider);
    }
}

스프링 시큐리티에서는 자동적으로 CSRF 보호가 실행되기 때문에,
당장 관련 설정을 하지 않는다면 csrf.disable()을 설정해 CSRF보호를 꺼 놓아야 개발하기 편하다. (위 코드엔 없다)

만약 보호를 꺼 놓지 않는다면 스프링 시큐리티가 CSRF로부터 보호를 시작하기 때문에 정상적으로 작동시키려면
서버에서 토큰을 발행하고 클라이언트 측에서도 서버에 요청할 때에 CSRF토큰을 포함해서 보내야 하기 때문이다.

 

 

3. SecurityConfig클래스에서 호출한 authenticationProvider인터페이스를 상속받아 클래스를 작성한다.

@Component
public class UserAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private AuthService authService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String userId = authentication.getName();
        String password = authentication.getCredentials().toString();
        return authService.authenticate(userId, password);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}

Authentication은 세션 정보를 저장해놓는 컨텍스트이다.

클래스 안에는 Principal(아이디), Authority(권한), Credential(패스워드)이 있고,

 

사용자가 화면을 열면 > 스프링 시큐리티가 UserAuthenticcationProvider을 열어서 아이디 패스워드값을 Authentication컨텍스트에 저장 > 서비스 클래스로 가서 DB검증하고, 패스워드 값 맞춰서 보낼 정보 중 민감한 정보는 지우고, 권한 부여하고(DB에 기록되어 있는) > 접근을 허용하는 방식으로 진행된다.

 

Spring Security는 Filter 기반으로 운용되고, SpringMVC와는 독립적으로 동작한다는걸 알면 이해하기 수월하다.

 

 

4. 인증을 위한 서비스 클래스를 만들어준다.

@Service
public class AuthService {

    @Autowired
    private UserMapper userMapper;

    public Authentication authenticate(String userId, String password) {
        UserVo userVo = userMapper.getUser(userId);
        if (userVo != null) {
            if (userVo.getPassword().equals(password)) { 
                userVo.setPassword(null); // 보안을 위해 확인이 끝나면 삭제한다.
                List<SimpleGrantedAuthority> authorities = new ArrayList<>();
                authorities.add(new SimpleGrantedAuthority(userVo.getRole()));  
                return new UsernamePasswordAuthenticationToken(userVo, null, authorities);
            }
        }

        throw new BadCredentialsException("No such user.");
    }

 

 

 

 

'Java > SpringBoot' 카테고리의 다른 글

Spring boot : Mustache 사용시 한글 인코딩 설정  (0) 2024.03.11
Spring Security CSRF 설정  (0) 2021.12.09
Logback 기본 설정  (0) 2021.12.07

< Logging 프레임워크 >

1. log4j

: 개발 중단, 최근 보안 이슈로 사용하지 않는 게 낫다... 

 

참고 : 보안뉴스 권준 '거의 모든 서버가 위험하다! 매우 치명적인 '로그4j'보안 취약점 발견'

https://www.boannews.com/media/view.asp?idx=103257

 

2. logback

: slf4j의 구현체. 스프링부트에서는 기본으로 설정되어 있다.

 

 

< 로그의 레벨 >

1. Error : 빠른 조치가 필요한 단계
2. Warn : 로직상 유효성 확인, 예상가능한 문제로 인한 예외처리, 운영엔 문제없음
3. Info : 참고할 만한 사항
------------------------------------------------
4. debug : 개발단계에서 사용. sql 로깅 가능
5. trace : 모든 레벨에 대한 로깅이 추적된다.

 

 

< logback-spring.xml >

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="60 seconds">
    <property name="LOG_DIR" value="log"/>
    <property name="LOG_PATH_NAME" value="${LOG_DIR}/data.log" />
    
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSSS} [%12t] %-5level %logger{5} - %msg %n</pattern>
        </encoder>
    </appender>

    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSSS} [%12t] %-5level %logger{5} - %msg %n</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>C:\logs\%d{yyyy-MM-dd}_log.log</FileNamePattern>
            <MaxHistory>365</MaxHistory>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>
</configuration>

내가 쓰는 logback-spring.xml 포맷이다.

 

로그의 경우 아래와 같이 application.properties에서도 설정이 가능하지만,

logging.level.root=debug
logging.level.com.springboottest.controller=info
logging.path=c:/logs/
logging.file=c:/logs/my.log
logging.config=classpath:/logback.logback.xml

스프링부트는 classpath에 logback-spring.xml이 있으면 알아서 읽기 때문에

상세 설정을 위해 xml파일을 만들어 따로 분리해 두는게 편리하다.

 

스프링부트는 logback-spring.xml이라는 파일이 없다면 properties.yml파일을 읽는다.

우선순위는 .yml > .xml 이다.

 

'Java > SpringBoot' 카테고리의 다른 글

Spring boot : Mustache 사용시 한글 인코딩 설정  (0) 2024.03.11
Spring Security CSRF 설정  (0) 2021.12.09
Spring Security 기본 설정  (0) 2021.12.08

+ Recent posts