개발 공부

spring boot 2 security error : 'X-Frame-Options' to 'deny'. 본문

자바, 스프링, 웹개발/웹개발

spring boot 2 security error : 'X-Frame-Options' to 'deny'.

아이셩짱셩 2020. 12. 14. 13:19

참고)

www.one-tab.com/page/8EDLjdh2QymvI5nmTovKlA

 

문제 발생)

- iframe(네이버 스마트 에디터) 사용 시 아래 오류 발생

 

Refused to display '... url ...' in a frame beacuse it set 'X-Frame-Options' to 'deny'.

 

원인)

- iframe 을 사용하기 위해서는 X-Frame-Options 를 허용으로 바꿔줘야함.

 

## X-Frame-Options ##

deny
   어떠한 사이트에서도 frame 상에서 보여질 수 없습니다.

sameorigin
   동일한 사이트의 frame에서만 보여집니다. 해당 스펙 안에서 브라우저 벤더가 최상위(top level), 혹은 부모(parent), 모든 체인(whole chain)에서 적용할지를 결정하도록 맡겨집니다. 하지만 모든 조상(ancestor)이 동일한 사이트에서 제공되지 않으면 이 옵션은 그다지 유용하지 않다고 논의되고 있습니다. (참고 bug 725490). 상세 지원사항에 대한 참고 Browser compatibility.

allow-from uri
   지정된 특정 uri의 frame 에서만 보여집니다. 파이어폭스에서는 sameorigin 과 동일한 문제를 겪고 있습니다. 즉 동일한 사이트에 있는지에 대해서 frame의 조상(ancestor)을 확인하지 않습니다.

 

 

 

해결 방법)

## X-Frame-Options 설정 방법 (중 택 1) ##

아파치 설정 Configuring Apache (httpd.conf)

Header always append X-Frame-Options DENY


Nginx 설정 Configuring Nginx (nginx.conf)

add_header X-Frame-Options sameorigin;

 

톰캣 설정 Configuring Tomcat(web.xml)

<filter>
	<filter-name>httpHeaderSecurity</filter-name>
	<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
	<async-supported>true</async-supported>
	<init-param>
		<param-name>antiClickJackingEnabled</param-name>
		<param-value>true</param-value>
	</init-param>
	<init-param>
		<param-name>antiClickJackingOption</param-name>
		<param-value>DENY</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>httpHeaderSecurity</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

 

스프링 부트 세큐리티 (application.yml 등) 설정 Configuring spring boot security(application.properties/~.yml)

...

# SECURITY (SecurityProperties)
security.user.name=user # login username
security.user.password= # login password
security.user.role=USER # role assigned to the user
security.require-ssl=false # advanced settings ...
security.enable-csrf=false
security.basic.enabled=true
security.basic.realm=Spring
security.basic.path= # /**
security.headers.xss=false
security.headers.cache=false
security.headers.frame=false
security.headers.contentType=false
security.headers.hsts=all # none / domain / all
security.sessions=stateless # always / never / if_required / stateless
security.ignored=false

...

 

제약사항(?))

가장 간단한 application properties로 설정 시 아래와 같은 제약사항 발생.

이유 -> 보안 설정을 간소화하기 위해 spring boot 2에서는 아래의 설정 항목을 없앰.

To simplify the security-related configuration, Spring Boot 2 has removed the following Spring Boot 1 properties:

security.basic.authorize-mode
security.basic.enabled
security.basic.path
security.basic.realm
security.enable-csrf
security.headers.cache
security.headers.content-security-policy
security.headers.content-security-policy-mode
security.headers.content-type
security.headers.frame
security.headers.hsts
security.headers.xss
security.ignored
security.require-ssl
security.sessions

 

해결)

app 실행 시 설정될 수 있도록 

WebSecurityConfigurerAdapter 를 확장하는 custom security config에서 아래 설정 추가

http.headers().frameOptions().sameOrigin();	//security 설정 추가

 

예시)

package com.test.app.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	

	@Override
	protected void configure(HttpSecurity http) throws Exception {
    	
        // security 설정 추가
        http.headers().frameOptions().sameOrigin();
		
        http
          .authorizeRequests()
          .antMatchers("/foo", "/foo/bar").permitAll()
          .anyRequest()
          .authenticated()
          .and()
          .httpBasic();
	}
}

 

Comments