背景
Spring-bootで埋め込み用ページを作りました。iframeで他のサイトから見せるやつ。
この際、Spring Securityを導入しておりデフォルトでHTTPヘッダの「X-Frame-Options」がDENYになり、埋め込んだページが表示されませんでした。
このX-Frame-Options自体は、普通のページではクリックジャッキングを抑止するためにDENYであるほうが良いので、埋め込み用のページだけこのヘッダを送らない設定にした方が良いと判断しました。
ただ「特定のURLだけ、X-Frame-Optionsを設定する」のが、ちょっとややこしかったので、まとめてみました。
他のHTTP Headerも、もし必要であればURL毎に設定できるようになると思います(未検証)。
目的
対象URL | X-Frame-Options |
---|---|
example.com/contents/embed/** | ヘッダ自体送信しない |
上記のURL以外 | DENY(デフォルト) |
参考
同じ悩みの人がStack overflowに。
なので、今回はこれを参考にしました。
Disable X-FrameOptions response header for a URL Spring Security JAVA config
https://stackoverflow.com/questions/42257402/disable-x-frameoptions-response-header-for-a-url-spring-security-java-config
設定
同じ「configure(HttpSecurity http)」で設定すると、全URLに影響が及んでしまいます。
WebSecurityConfigurerAdapterをextendsしたものを複数用意するのが鍵だそうです。
@EnableWebSecurity
public class WebMVCSecurity {
// 認証のための設定をする。オプション。これはただのサンプルで、X-Frame-Optionsには影響しないので変えてもOK。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
// ここが一番大事。
// WebSecurityConfigurerAdapterのインスタンスを作成。@Orderアノテーションで読み込む順番を設定。
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
// 「"/contents/embed/**"」のように、適用したいURLを指定する。
// 今回はヘッダ設定無しにしたかったので、「.headers().frameOptions().disable()」とした。
// 「.headers().frameOptions().sameOrigin()」などの設定もあるので、調べてみてください。
http.antMatcher("/contents/embed/**").headers().frameOptions().disable();
}
}
// もう一つ、WebSecurityConfigurerAdapterのインスタンスを作成。
// 「"/contents/embed/**"」に該当しないURLは、ここの設定が適用されます。
// @Orderアノテーションを付けなかったら、他の@Orderの後に読み込まれるとのことです。
@Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
// などなど。プロジェクトに応じて設定してください。
}
}
}
以上です。