#概要
Spring SecurityとSpring MVCをxmlを使わずに設定してみた際のメモ。
完全なソースはGutHub
#設定内容
- 認証エラーの場合はログインページを表示する
- 但し、Ajaxリクエストの場合はHTTPステータス401を返す
- Thymeleafで
sec:authorize="hasRole('ROLE_ADMIN')"
のように、ロールによって表示を切り替えられるようにする
#必要な依存関係
使用する主なモジュールとバージョン
- SpringSecurity : 4.0.0.M1
- SpringMVC : 4.0.5.RELEASE
- Thymeleaf : 2.1.3.RELEASE
詳細はpom.xmを参照
#SpringSecurityの設定
今回はAjaxリクエストの場合はログインページにリダイレクトするのではなくて、HTTPステータス401を返したいので、リクエストヘッダにX-Requested-With: XMLHttpRequest
があった場合のAuthenticationEntryPointを追加しています。
WebSecurityConfig
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles("ADMIN").and()
.withUser("user").password("user").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(
"/",
"/css/**",
"/login",
"/logout").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.and()
.logout()
.logoutRequestMatcher(logoutRequestMatcher())
.invalidateHttpSession(true)
.and()
.csrf()
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(
ajaxAuthenticationEntryPoint(),
ajaxRequestMatcher()
);
}
@Bean
public AuthenticationEntryPoint ajaxAuthenticationEntryPoint() {
return new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
};
}
@Bean
public RequestMatcher ajaxRequestMatcher() {
return new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest");
}
@Bean
public RequestMatcher logoutRequestMatcher() {
return new AntPathRequestMatcher("/logout");
}
}
#SpringMVCの設定
リソースハンドラとビューを返すだけのコントローラーを追加しています。
それから@Import(ThymeleafConfig.class)
でThymeleafの設定をインポート。
WebMvcConfig
@Configuration
@EnableWebMvc
@Import(ThymeleafConfig.class)
@ComponentScan(
basePackageClasses = {AjaxTestController.class}
)
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**").addResourceLocations("/WEB-INF/views/css/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/member").setViewName("member");
}
}
#Tymeleafの設定
ThymeleafとSpringSecurityを連携するためにSpringSecurityDialectを追加。
開発中はキャッシュされない方がいいのでresolver.setCacheable(false);
それから文字コードの設定は2箇所あるので注意。
ThymeleafConfig
@Configuration
public class ThymeleafConfig {
private final String CHARACTER_ENCODING = "UTF-8";
@Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver
= new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding(CHARACTER_ENCODING);
resolver.setCacheable(false);
return resolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.addDialect(springSecurityDialect());
return engine;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding(CHARACTER_ENCODING);
return resolver;
}
@Bean
public IDialect springSecurityDialect() {
SpringSecurityDialect dialect = new SpringSecurityDialect();
return dialect;
}
}