読者です 読者をやめる 読者になる 読者になる

m_shige1979のささやかな抵抗と欲望の日々

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

なんとなく作ったサイト

http://www.it-check-matome.info/


Github(注意すること)

https://github.com/mshige1979

Spring Bootで複数のフィルターを設定する

Java Spring Boot Spring Filter

フィルタ内で全て1つでまとめるより

複数に分けたほうが管理し易いよね

やること

  1. Filterをimplementsしたクラスを作成
  2. @Componentsアノテーションは設定しない
  3. WebMvcConfigurerAdapterを継承したクラスで使用するフィルタを設定

フィルタ準備

Sample1Filter.java
package com.example.config.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

public class Sample1Filter implements Filter {
	
	private static final Logger logger = LoggerFactory.getLogger(Sample1Filter.class);

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// 起動時に実行される
		logger.info("Sample1 Filter init");
	}
	 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// リクエスト発行時に実行される
		logger.info("Sample1 Filter doFilter start");
		chain.doFilter(request, response);
		logger.info("Sample1 Filter doFilter end");
	}

	@Override
	public void destroy() {
		// 終了時に実行される
		logger.info("Sample1 Filter destroy");
	}
	
}
Sample2Filter.java
package com.example.config.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

public class Sample2Filter implements Filter {
	
	private static final Logger logger = LoggerFactory.getLogger(Sample2Filter.class);

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// 起動時に実行される
		logger.info("Sample2 Filter init");
	}
	 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// リクエスト発行時に実行される
		logger.info("Sample2 Filter doFilter start");
		chain.doFilter(request, response);
		logger.info("Sample2 Filter doFilter end");
	}

	@Override
	public void destroy() {
		// 終了時に実行される
		logger.info("Sample2 Filter destroy");
	}
	
}

フィルタ設定用クラス

WebConfig.java
package com.example.config;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.example.config.filter.Sample1Filter;
import com.example.config.filter.Sample2Filter;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
	
	@Bean
	public FilterRegistrationBean sampleFilter1() {		
		FilterRegistrationBean bean = new FilterRegistrationBean();
		bean.setFilter(new Sample1Filter());
		bean.setOrder(2);
		return bean;
	}
	
	@Bean
	public FilterRegistrationBean sampleFilter2() {		
		FilterRegistrationBean bean = new FilterRegistrationBean();
		bean.setFilter(new Sample2Filter());
		bean.setOrder(1);
		return bean;
	}
	
}

実行結果

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.3.RELEASE)

2016-12-30 17:23:45.163  INFO 10234 --- [           main] c.e.SpringSampleFilter01Application      : Starting SpringSampleFilter01Application on mshige1979MBA.local with PID 10234 (/Users/matsumotoshigeharu/Documents/workspace/spring_sample_filter01/target/classes started by matsumotoshigeharu in /Users/matsumotoshigeharu/Documents/workspace/spring_sample_filter01)
2016-12-30 17:23:45.167  INFO 10234 --- [           main] c.e.SpringSampleFilter01Application      : No active profile set, falling back to default profiles: default
2016-12-30 17:23:45.569  INFO 10234 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3a93b025: startup date [Fri Dec 30 17:23:45 JST 2016]; root of context hierarchy
2016-12-30 17:23:47.049  INFO 10234 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [class org.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$9e478f9c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2016-12-30 17:23:47.130  INFO 10234 --- [           main] .w.s.a.s.AnnotationActionEndpointMapping : Supporting [WS-Addressing August 2004, WS-Addressing 1.0]
2016-12-30 17:23:47.672  INFO 10234 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-12-30 17:23:47.688  INFO 10234 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-12-30 17:23:47.689  INFO 10234 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.6
2016-12-30 17:23:47.821  INFO 10234 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-12-30 17:23:47.822  INFO 10234 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2258 ms
2016-12-30 17:23:48.109  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-12-30 17:23:48.110  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-12-30 17:23:48.110  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-12-30 17:23:48.110  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2016-12-30 17:23:48.110  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'sample2Filter' to: [/*]
2016-12-30 17:23:48.110  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'sample1Filter' to: [/*]
2016-12-30 17:23:48.111  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2016-12-30 17:23:48.112  INFO 10234 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'messageDispatcherServlet' to [/services/*]
2016-12-30 17:23:48.145  INFO 10234 --- [ost-startStop-1] com.example.config.filter.Sample2Filter  : Sample2 Filter init
2016-12-30 17:23:48.146  INFO 10234 --- [ost-startStop-1] com.example.config.filter.Sample1Filter  : Sample1 Filter init
2016-12-30 17:23:48.481  INFO 10234 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3a93b025: startup date [Fri Dec 30 17:23:45 JST 2016]; root of context hierarchy
2016-12-30 17:23:48.567  INFO 10234 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/sample1/index],methods=[GET]}" onto public java.lang.String com.example.controller.Sample1Controller.index(org.springframework.ui.Model)
2016-12-30 17:23:48.571  INFO 10234 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-12-30 17:23:48.572  INFO 10234 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2016-12-30 17:23:48.634  INFO 10234 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-12-30 17:23:48.635  INFO 10234 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-12-30 17:23:48.701  INFO 10234 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-12-30 17:23:49.657  INFO 10234 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-12-30 17:23:49.792  INFO 10234 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-12-30 17:23:49.798  INFO 10234 --- [           main] c.e.SpringSampleFilter01Application      : Started SpringSampleFilter01Application in 5.262 seconds (JVM running for 5.969)
2016-12-30 17:23:58.031  INFO 10234 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2016-12-30 17:23:58.032  INFO 10234 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2016-12-30 17:23:58.072  INFO 10234 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 40 ms
2016-12-30 17:23:58.087  INFO 10234 --- [nio-8080-exec-1] com.example.config.filter.Sample2Filter  : Sample2 Filter doFilter start
2016-12-30 17:23:58.088  INFO 10234 --- [nio-8080-exec-1] com.example.config.filter.Sample1Filter  : Sample1 Filter doFilter start
2016-12-30 17:23:58.409  INFO 10234 --- [nio-8080-exec-1] com.example.config.filter.Sample1Filter  : Sample1 Filter doFilter end
2016-12-30 17:23:58.409  INFO 10234 --- [nio-8080-exec-1] com.example.config.filter.Sample2Filter  : Sample2 Filter doFilter end
2016-12-30 17:24:02.681  INFO 10234 --- [2)-192.168.10.3] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
2016-12-30 17:24:02.682  INFO 10234 --- [2)-192.168.10.3] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3a93b025: startup date [Fri Dec 30 17:23:45 JST 2016]; root of context hierarchy
2016-12-30 17:24:02.684  INFO 10234 --- [2)-192.168.10.3] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2016-12-30 17:24:03.757  INFO 10234 --- [ost-startStop-2] com.example.config.filter.Sample2Filter  : Sample2 Filter destroy
2016-12-30 17:24:03.757  INFO 10234 --- [ost-startStop-2] com.example.config.filter.Sample1Filter  : Sample1 Filter destroy

こんな感じですかね…

所感

なんとなくDIなどの動きはわかってきたけどBeanの仕組みがいまいちわかってない(´・ω・`)
データの流れを上手く把握しないと記載方法などに影響ができるの少しずつでも理解しておく必要がある。
日本語のマニュアルどっかにないかな〜

Spring Bootでフィルターを設定する

Java Spring Boot Spring

フィルタ

起動時、リクエスト、終了時などになんらかの処理を仕込みたい場合に設定する処理のこと
HTTPリクエスト時などで特定のヘッダが存在しない場合は処理を実施しないなどに使用する感じ?

設定方法

  1. Filterをimplemtsしたクラスを実装
  2. @Componentsアノテーションを付与

でイケる感じ

実装

SampleFilter.java
package com.example.config.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SampleFilter implements Filter {
	
	private static final Logger logger = LoggerFactory.getLogger(SampleFilter.class);

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// 起動時に実行される
		logger.info("Sample Filter init");
	}
	 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// リクエスト発行時に実行される
		logger.info("Sample Filter doFilter start");
		chain.doFilter(request, response);
		logger.info("Sample Filter doFilter end");
	}

	@Override
	public void destroy() {
		// 終了時に実行される
		logger.info("Sample Filter destroy");
	}
	
}

※これだけでアプリにフィルタが実装される感じらしい

実行ログ

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.3.RELEASE)

2016-12-30 16:44:59.624  INFO 10081 --- [           main] c.e.SpringSampleFilter01Application      : Starting SpringSampleFilter01Application on mshige1979MBA.local with PID 10081 (/Users/matsumotoshigeharu/Documents/workspace/spring_sample_filter01/target/classes started by matsumotoshigeharu in /Users/matsumotoshigeharu/Documents/workspace/spring_sample_filter01)
2016-12-30 16:44:59.626  INFO 10081 --- [           main] c.e.SpringSampleFilter01Application      : No active profile set, falling back to default profiles: default
2016-12-30 16:45:00.109  INFO 10081 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3a93b025: startup date [Fri Dec 30 16:45:00 JST 2016]; root of context hierarchy
2016-12-30 16:45:01.110  INFO 10081 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [class org.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$311b2b8c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2016-12-30 16:45:01.172  INFO 10081 --- [           main] .w.s.a.s.AnnotationActionEndpointMapping : Supporting [WS-Addressing August 2004, WS-Addressing 1.0]
2016-12-30 16:45:01.634  INFO 10081 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-12-30 16:45:01.651  INFO 10081 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-12-30 16:45:01.653  INFO 10081 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.6
2016-12-30 16:45:01.805  INFO 10081 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-12-30 16:45:01.805  INFO 10081 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1700 ms
2016-12-30 16:45:02.008  INFO 10081 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2016-12-30 16:45:02.010  INFO 10081 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'messageDispatcherServlet' to [/services/*]
2016-12-30 16:45:02.013  INFO 10081 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-12-30 16:45:02.014  INFO 10081 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-12-30 16:45:02.014  INFO 10081 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-12-30 16:45:02.014  INFO 10081 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2016-12-30 16:45:02.014  INFO 10081 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'sampleFilter' to: [/*]
2016-12-30 16:45:02.036  INFO 10081 --- [ost-startStop-1] com.example.config.filter.SampleFilter   : Sample Filter init
2016-12-30 16:45:02.341  INFO 10081 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3a93b025: startup date [Fri Dec 30 16:45:00 JST 2016]; root of context hierarchy
2016-12-30 16:45:02.421  INFO 10081 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/sample1/index],methods=[GET]}" onto public java.lang.String com.example.controller.Sample1Controller.index(org.springframework.ui.Model)
2016-12-30 16:45:02.426  INFO 10081 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-12-30 16:45:02.426  INFO 10081 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2016-12-30 16:45:02.470  INFO 10081 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-12-30 16:45:02.471  INFO 10081 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-12-30 16:45:02.514  INFO 10081 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-12-30 16:45:03.050  INFO 10081 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-12-30 16:45:03.122  INFO 10081 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-12-30 16:45:03.127  INFO 10081 --- [           main] c.e.SpringSampleFilter01Application      : Started SpringSampleFilter01Application in 4.188 seconds (JVM running for 5.127)
2016-12-30 16:45:13.216  INFO 10081 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2016-12-30 16:45:13.216  INFO 10081 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2016-12-30 16:45:13.233  INFO 10081 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 17 ms
2016-12-30 16:45:13.249  INFO 10081 --- [nio-8080-exec-1] com.example.config.filter.SampleFilter   : Sample Filter doFilter start
2016-12-30 16:45:13.461  INFO 10081 --- [nio-8080-exec-1] com.example.config.filter.SampleFilter   : Sample Filter doFilter end
2016-12-30 16:45:18.987  INFO 10081 --- [nio-8080-exec-2] com.example.config.filter.SampleFilter   : Sample Filter doFilter start
2016-12-30 16:45:18.992  INFO 10081 --- [nio-8080-exec-2] com.example.config.filter.SampleFilter   : Sample Filter doFilter end
2016-12-30 16:45:23.424  INFO 10081 --- [2)-192.168.10.3] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
2016-12-30 16:45:23.424  INFO 10081 --- [2)-192.168.10.3] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3a93b025: startup date [Fri Dec 30 16:45:00 JST 2016]; root of context hierarchy
2016-12-30 16:45:23.427  INFO 10081 --- [2)-192.168.10.3] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2016-12-30 16:45:24.489  INFO 10081 --- [ost-startStop-2] com.example.config.filter.SampleFilter   : Sample Filter destroy

動きました
作成するだけで起動するのはちょっと不安な感じもするけど楽といえば楽ですね(^^)

所感

どんな処理を設定するかは今後考えるとしてリクエストの前後などに処理を簡単に設定できるのは結構便利な気がします。
RestAPIなどのトークン制御などに使えるのかも…

Spring Bootで独自の認証を組み込む

Spring Boot Spring Java 認証

認証を独自に実装したい

DBの認証やアルゴリズムがちょっと特殊な場合など

今回やったこと

・AuthenticationProviderを実装したAuthenticationProviderImplクラスを作成してここで認証を実施
・WebSecurityConfigurerAdapterにAuthenticationProviderImplを設定する

独自認証実装

AuthenticationProviderImpl.java
package com.example.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import com.example.entity.User;

@Component
public class AuthenticationProviderImpl implements AuthenticationProvider {
	
	private static final Logger logger = LoggerFactory.getLogger(AuthenticationProviderImpl.class);
	
	@Override
	public Authentication authenticate(Authentication auth) throws AuthenticationException {
		
		// ユーザーとパスワードを取得
		String id = auth.getName();
        String password = auth.getCredentials().toString();
		
        // 未設定の場合はエラー
        if ("".equals(id) || "".equals(password))  {
            // 例外はSpringSecurityにあったものを適当に使用
            throw new AuthenticationCredentialsNotFoundException("ログイン情報に不備があります。");
        }
        
        // 認証情報を取得
        User user = authCheck(id, password);
        if (user == null) {
        	throw new AuthenticationCredentialsNotFoundException("ログイン情報が存在しません。");
        }
		// トークンを返却
		return new UsernamePasswordAuthenticationToken(user, password, auth.getAuthorities());
	}

	@Override
	public boolean supports(Class<?> token) {
		return UsernamePasswordAuthenticationToken.class.isAssignableFrom(token);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private User authCheck(String username, String password) {
		User user = null;
		
		List<Map<String, String>> list = new ArrayList<>();
		Map map;
		map = new HashMap<String, String>(){
			private static final long serialVersionUID = 1L;
			{put("username", "admin");}
			{put("password", "password");}
			{put("role", "ADMIN");}
		};
		list.add(map);
		map = new HashMap<String, String>(){
			private static final long serialVersionUID = 1L;
			{put("username", "user");}
			{put("password", "password");}
			{put("role", "USER");}
		};
		list.add(map);
		map = new HashMap<String, String>(){
			private static final long serialVersionUID = 1L;
			{put("username", "hogehoge");}
			{put("password", "password2");}
			{put("role", "USER");}
		};
		list.add(map);
		
		for(Map map1 : list) {
			if (map1.get("username").equals(username) && map1.get("password").equals(password)){
				user = new User();
				user.setUsername(map1.get("username").toString());
				user.setPassword(map1.get("password").toString());
				user.setRole(map1.get("role").toString());
				break;
			}
		}
		
		return user;
	}

}

※独自実装対応

セキュリティ設定

WebSecurityConfig.java
package com.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.example.handler.SampleAuthenticationFailureHandler;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
		// 認可の設定
        httpSecurity
        	.authorizeRequests()
        	.antMatchers("/css/**", "/img/**", "/js/**", "/login").permitAll()	// /loginは認証なしでアクセス可能
        	.antMatchers("/admin/**").hasRole("ADMIN")	// ADMINユーザーのみアクセス可能
        	.antMatchers("/user/**").hasRole("USER")	// USERユーザーのみアクセス可能
        	.anyRequest()
        	.authenticated();
        
        // ログイン設定
        httpSecurity
        	.formLogin()
        	.loginProcessingUrl("/login")	// 認証処理用
        	.loginPage("/login")	// ログインページ
        	.failureHandler(new SampleAuthenticationFailureHandler())	// 認証失敗時のハンドラクラス
        	.usernameParameter("username")	// ユーザー名のパラメータ
        	.passwordParameter("password")	// パスワードのパラメータ
        	.defaultSuccessUrl("/")	// 認証成功時の遷移先
        	.and();
        
        // ログアウト設定
        httpSecurity
        	.logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout**"))       // ログアウト処理のパス
            .logoutSuccessUrl("/login");	// ログイン完了後のパス 
    }
    
    @Configuration
    protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
        
        @Autowired
        private AuthenticationProviderImpl authenticationProvider;
        
        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
        	// 認証方法を設定する
        	auth.authenticationProvider(authenticationProvider);
        }
    }
	
}

※authenticationProviderで認証設定を行う

エンティティ

User.java
package com.example.entity;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.springframework.data.annotation.Transient;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table(name = "user")
public class User implements UserDetails {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@Column(name="username")
	private String username;
	
	@Column(name="password")
	private String password;
	
	@Column(name="role")
	private String role;
	
	public void setUsername(String username){
		this.username = username;
	}
	
	public void setPassword(String password){
		this.password = password;
	}
	
	public String getRole() {
		return this.role;
	}
	
	public void setRole(String role){
		this.role = role;
	}
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		// TODO Auto-generated method stub
		Collection<GrantedAuthority> authorityList = new ArrayList<>();
		authorityList.add(new SimpleGrantedAuthority("ROLE_" + this.role));
		return authorityList;
	}

	@Override
	public String getPassword() {
		// TODO Auto-generated method stub
		return this.password;
	}

	@Override
	public String getUsername() {
		// TODO Auto-generated method stub
		return this.username;
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return true;
	}

}

※user情報設定用にsetterを付与

所感

これでなんとかDB以外のアクセスも対応できそう。
つかうかどうかはまだ不明ですがね…

Spring Bootで独自のエラー画面を表示したい

Spring Spring Boot エラー画面

エラー画面がほしい

システムの画面はちょっと困る

やること

・EmbeddedServletContainerCustomizerを実装する
・ErrorControllerクラスを作成する
・Viewを作成する

EmbeddedServletContainerCustomizer実装

Customizer.java
package com.example.error;

import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

@Component
public class Customizer implements EmbeddedServletContainerCustomizer {

	@Override
	public void customize(ConfigurableEmbeddedServletContainer container) {
		container.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/403"));
		container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
	}

}

※@Componentを付与して対応

エラー用

ErrorController.java
package com.example.controller.error;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.http.HttpStatus;

@Controller
public class ErrorController {
	
	@RequestMapping(value = "/403", method = RequestMethod.GET)
	@ResponseStatus(HttpStatus.NOT_FOUND)
	public String forbidden() {
		return "errorpage/403";
	}
	
	@RequestMapping(value = "/404", method = RequestMethod.GET)
	@ResponseStatus(HttpStatus.NOT_FOUND)
	public String notFound() {
		return "errorpage/404";
	}
	
}

※エラーページを指定する

エラー画面

errorpage/403.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
</head>
<body>
	403 Forbidden
</body>
</html>
errorpage/404.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
</head>
<body>
	404 Not Found
</body>
</html>


単純にtemplates配下にerrorディレクトリ作成するだけでも対応できるかも…

画面

f:id:m_shige1979:20161227005540p:plain

Spring Bootでセキュリティに権限を設定する

Spring Boot Spring 権限 Java 認証

認可

ユーザーに特定の条件を付与してアクセス権限みたいなものを設定する
今回は1つの権限で1つのURLへのアクセスを制御する。
実際はロールとかいうもので1ユーザーが複数持てるように管理すべきだが面倒なんで…

やること

ユーザーテーブルに権限のエリアを追加
WebSecurityConfigurerAdapterの派生クラスを修正
ユーザーのエンティティクラスで権限を設定するように対応

テーブル

DROP TABLE if EXISTS user;
create table if not exists user (
   id          int          not null auto_increment,
   username    varchar(255) not null,
   password    varchar(255) not null,
   role        varchar(255) not null,
   primary key (id)
);

※roleを追加

セキュリティ設定

WebSecurityConfig.java
package com.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.example.handler.SampleAuthenticationFailureHandler;
import com.example.service.UserServiceImpl;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
		// 認可の設定
        httpSecurity
        	.authorizeRequests()
        	.antMatchers("/css/**", "/img/**", "/js/**", "/login").permitAll()	// /loginは認証なしでアクセス可能
        	.antMatchers("/admin/**").hasRole("ADMIN")	// ADMINユーザーのみアクセス可能
        	.antMatchers("/user/**").hasRole("USER")	// USERユーザーのみアクセス可能
        	.anyRequest()
        	.authenticated();
        
        // ログイン設定
        httpSecurity
        	.formLogin()
        	.loginProcessingUrl("/login")	// 認証処理用
        	.loginPage("/login")	// ログインページ
        	.failureHandler(new SampleAuthenticationFailureHandler())	// 認証失敗時のハンドラクラス
        	.usernameParameter("username")	// ユーザー名のパラメータ
        	.passwordParameter("password")	// パスワードのパラメータ
        	.defaultSuccessUrl("/")	// 認証成功時の遷移先
        	.and();
        
        // ログアウト設定
        httpSecurity
        	.logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout**"))       // ログアウト処理のパス
            .logoutSuccessUrl("/login");	// ログイン完了後のパス 
    }
    
    @Configuration
    protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
        @Autowired
        UserServiceImpl userDetailsService;

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            // 認証するユーザーを設定する
            auth.userDetailsService(userDetailsService);
        }
    }
	
}

エンティティ

User.java
package com.example.entity;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.springframework.data.annotation.Transient;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table(name = "user")
public class User implements UserDetails {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@Column(name="username")
	private String username;
	
	@Column(name="password")
	private String password;
	
	@Column(name="role")
	private String role;
	
	public String getRole() {
		return this.role;
	}
	
	public void setRole(String role){
		this.role = role;
	}
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		// TODO Auto-generated method stub
		Collection<GrantedAuthority> authorityList = new ArrayList<>();
		authorityList.add(new SimpleGrantedAuthority("ROLE_" + this.role));
		return authorityList;
	}

	@Override
	public String getPassword() {
		// TODO Auto-generated method stub
		return this.password;
	}

	@Override
	public String getUsername() {
		// TODO Auto-generated method stub
		return this.username;
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return true;
	}

}

※今回は権限テーブルで複数持たないのでUserDetailsを実装したgetAuthoritiesメソッドでROLEを生成して設定するように対応
※ROLE_XXXのような形で設定しておく必要があります。

動作

Spring Bootで認証を試す

Spring Boot Java 認証

なんか結構難しいけど

いろいろな記事見ててモヤモヤしてて他の事が手につかなくなったのでちょっとだけ試す。

認証機能

ログインやログアウトを行う機能

プロジェクト作成時の設定

pom.xml
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

データベース設定

create.sql
DROP TABLE if EXISTS user;
create table if not exists user (
   id          int          not null auto_increment,
   username    varchar(255) not null,
   password    varchar(255) not null,
   primary key (id)
);
data.sql
insert into user (id, username, password) values (1, 'user', 'password');

アプリケーション設定

application.properties
# server
server.port=8081

# database datasource
spring.datasource.url=jdbc:mysql://192.168.33.10/myapp?useSSL=false
spring.datasource.username=app
spring.datasource.password=Password123@
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

# database jpa
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect

# default user
#security.user.name=admin
#security.user.password=admin

エンティティを作成

User.java
package com.example.entity;

import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table(name = "user")
public class User implements UserDetails {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@Column(name="username")
	private String username;
	
	@Column(name="password")
	private String password;
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getPassword() {
		// TODO Auto-generated method stub
		return this.password;
	}

	@Override
	public String getUsername() {
		// TODO Auto-generated method stub
		return this.username;
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return true;
	}

}

※認証用にUserDetailsを実装する必要があるらしい

リポジトリ

UserRepository.java
package com.example.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.entity.User;

@Repository
public interface UserRepository extends JpaRepository<User, Long>{
	public User findByUsername(String username);
}

※ユーザー名から取得用のメソッドを準備

サービス

UserServiceImpl.java
package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.example.entity.User;
import com.example.repository.UserRepository;

@Component
public class UserServiceImpl implements UserDetailsService{
	
	@Autowired
	private UserRepository userRepository;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		
		if (StringUtils.isEmpty(username)) {
			throw new UsernameNotFoundException("");
		}
		
		User user = userRepository.findByUsername(username);
		if (user == null) {
			throw new UsernameNotFoundException("");
		}
		
		return user;
	}

}

※UserDetailsServiceを実装してユーザー情報取得用の実装を行う

認証設定

WebSecurityConfig.java
package com.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.example.handler.SampleAuthenticationFailureHandler;
import com.example.service.UserServiceImpl;

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
		// 認可の設定
        httpSecurity
        	.authorizeRequests()
        	.antMatchers("/login").permitAll()	// /loginは認証なしでアクセス可能
        	.anyRequest()
        	.authenticated();
        
        // ログイン設定
        httpSecurity
        	.formLogin()
        	.loginProcessingUrl("/login")	// 認証処理用
        	.loginPage("/login")	// ログインページ
        	.failureHandler(new SampleAuthenticationFailureHandler())	// 認証失敗時のハンドラクラス
        	.usernameParameter("username")	// ユーザー名のパラメータ
        	.passwordParameter("password")	// パスワードのパラメータ
        	.defaultSuccessUrl("/")	// 認証成功時の遷移先
        	.and();
        
        // ログアウト設定
        httpSecurity
        	.logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout**"))       // ログアウト処理のパス
            .logoutSuccessUrl("/login");	// ログイン完了後のパス 
    }
    
    @Configuration
    protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
        @Autowired
        UserServiceImpl userDetailsService;

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            // 認証するユーザーを設定する
            auth.userDetailsService(userDetailsService);
        }
    }
	
}
SampleAuthenticationFailureHandler.java
package com.example.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

public class SampleAuthenticationFailureHandler implements AuthenticationFailureHandler {
	
	@Override
    public void onAuthenticationFailure(
            HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse,
            AuthenticationException authenticationException)
                    throws IOException, ServletException {

        String errorId = "";
        // ExceptionからエラーIDをセットする
        if(authenticationException instanceof BadCredentialsException){
            errorId = "ERROO1";
        }

        // ログイン画面にリダイレクトする
        httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/login"
                + "?error=" + errorId);
    }
}

画面

TopController.java
package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class TopController {
	
	@RequestMapping(value = "/", method = {RequestMethod.GET} )
	public String index(){
		return "index";
	}
	
}
LoginController.java
package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LoginController {
	
	@RequestMapping(value = "/login")
    public String index()
    {
        return "login";
    }
	
}
SampleController.java
package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class SampleController {
	
	@RequestMapping(value = "/sample")
    public String index()
    {
        return "sample";
    }
	
}
index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
</head>
<body>
  こんにちは!
  <form action="#" th:action="@{/logout}" method="POST">
    <input type="submit" value="ログアウト" />
  </form>
</body>
</html>
login.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ログイン</title>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
</head>
<body>
  <form action="" th:action="@{/login}" method="post">
    <p>
      ユーザーID:
      <input type="text" name="username" />
    </p>
    <p>
      パスワード:
      <input type="password" name="password" />
    </p>
    <p>
      <input type="submit" value="ログイン" />
    </p>
  </form>
  <div th:if="${session['SPRING_SECURITY_LAST_EXCEPTION']} != null">
    <span th:text="${session['SPRING_SECURITY_LAST_EXCEPTION'].message}"></span>
  </div>
</body>
</html>
sample.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
</head>
<body>
  こんにちは!サンプルページです
  <form action="#" th:action="@{/logout}" method="POST">
    <input type="submit" value="ログアウト" />
  </form>
</body>
</html>

動作サンプル


所感

認証ってセキュリティの部分なので結構深く作っているようでいろいろ混乱中です。
いろいろな人の記事みてもなんかいまいちわからないので動かしてみることにした
最初は勝手にbasic認証になっていたりと「いや、まだ使わないんですけど…」とかいう部分もあるので戸惑いながらもやってみて
なんとか認証自体は動いている状態までこぎつけた
今回はパスワードが平文のままだったりサンプルのコピペ部分もいくつかあるのでもう少しいろいろ試していかないと…

doma2のsql文調査

Java Doma2 DB SQL

SQL文の複合条件とか気になるので調べる

SELECT、INSERT、UPDATEらへんの挙動

SELECT

基本的にはSQLを作らなければならない

基本形
@Select
List<Item> findAll();

※@Selectアノテーションを付けたものが対象となります。

対応するSQL

select
    /*%expand*/*
from
    item
order by 
	id asc

SQLバインド変数が存在しないので直接設定する。

条件あり
@Select
Item findCondOne(Integer id);

※引数を設定することでsqlバインド変数を設定できる

select
    /*%expand*/*
from
    item 
where
	id = /* id */1
	
	
可変条件
@Select
List<Item> findCondAll(Integer id, String name, Integer price);

select
    /*%expand*/*
from
    item 

    where
/*%if id != null || name != null || price != null */
	/*%if id != null */
		id = /* id */1
	/*%end*/
	
	/*%if name != null */
		and
		name = /* name */'a'
	/*%end*/ 
	
	/*%if price != null */
		and
		price = /* price */1
	/*%end*/
/*%end*/

	
order by 
	id asc

※複数の条件を任意に条件に設定する場合はちょっと工夫が必要

INSERT

SQLを必要とする場合と必要ない場合がある。

基本形
@Insert
int insert(Item entity);

SQLは不要

SQLを作成する
@Insert(sqlFile = true)
int insertExecute(Item entity);

アノテーションにsqlFile = trueを付与

insert into item (name, price, create_at, update_at)
values (/* entity.getName() */'a',
        /* entity.getPrice() */100,
        /* entity.getCreateAt() */'2016-12-20T11:22:33',
        /* entity.getUpdateAt() */'2016-12-20T11:22:33')

バインド変数を設定する

UPDATE

SQLを必要とする場合と必要ない場合がある。

基本形
@Update
int update(Item entity);

SQLは不要

SQLを作成する
@Update(sqlFile = true)
int updateExecute(Item entity, String update);

update 
	item 
set 
	name = /* entity.getName() */'a',
	price = /* entity.getPrice() */1,
	update_at = /* entity.getUpdateAt() */'2016-12-24 02:56:55.33'
where
	id = /* entity.getId() */1
	and update_at = /* update */'2016-12-24 02:56:55.33'

バインド変数を設定する


今回はここまで