SpringBootã§SpringSecurityã使ã£ã¦ç¬èªèªè¨¼ã§ãã°ã¤ã³æ©è½ãå®è£ ãã¦ã¿ã¾ããã
ããã¥ã¡ã³ããåèã«ãã£ã¦ã¿ããã©ã詳ããæ¸ãã¦ãªãã¦ç解ã«è¦ãã¿çµæ§ãããã¾ããã
æçµçã«SpringSecurityã®ã½ã¼ã¹ãè¦ããã¨ã§èªè¨¼ãªãã¸ã§ã¯ãã®ä»çµã¿ãç解ãã¾ããã
æ¦è¦
SpringSecurityã§DBã使ç¨ãã¦èªè¨¼ããå ´åãSpringSecurityä»å±ã®ãã¼ãã«å®ç¾©ãè¡ãå¿
è¦ãããã¾ãã
ä»åã¯ãç¬èªãã¼ãã«ã使ã£ãèªè¨¼ãè¡ãããã¼ã«ã¯ä½¿ç¨ãã¾ããã
SpringSecurityã®è¨å®
SecurityConfigã¯ã©ã¹ãä½æããã¢ã¯ã»ã¹å¶éããã°ã¤ã³å¦çããã°ã¢ã¦ãå¦ççãå®ç¾©ãã¾ãã
èªè¨¼ãã§ãã¯å¦çã¯ã©ã¹
AuthenticationProviderã¤ã³ã¿ã¼ãã§ã¼ã¹ãç¶æ¿ãã¦ç¬èªã¯ã©ã¹ãä½æãã¾ãã
ãã®ã¯ã©ã¹ã§ç¬èªãã¼ãã«ãåç
§ãã¦èªè¨¼ãã§ãã¯å¦çãå®ç¾©ãã¾ãã
èªè¨¼ãªãã¸ã§ã¯ãä½æãµã¼ãã¹ã¯ã©ã¹
UserDetailsServiceã¤ã³ã¿ã¼ãã§ã¼ã¹ãç¶æ¿ãç¬èªã¯ã©ã¹ãä½æãã¾ãã
ãã®ã¯ã©ã¹ã§èªè¨¼å¾ã«ã·ã¹ãã å
ã§ä½¿ç¨ããèªè¨¼ãªãã¸ã§ã¯ããçæãã¾ãã
èªè¨¼ãªãã¸ã§ã¯ãã¯ã©ã¹
Userã¯ã©ã¹ãç¶æ¿ããã¯ã©ã¹ãä½æããusernameãpasswordãã£ã¼ã«ããå®ç¾©ãã¾ãã
usernameãpasswordãã£ã¼ã«ããå®ç¾©ãããã¨ã§ãã·ã¹ãã å
ã§èªè¨¼ãªãã¸ã§ã¯ãããªãã¸ã§ã¯ãã§æã¤ãã¨ãã§ããä»ã«å¿
è¦ãªæ
å ±ãæããããã¨ãã§ããããã«ãªãã¾ãã
ç°å¢
Eclipse | 4.3 |
---|---|
Java | 1.7 |
SpringBoot | 1.2.4 |
SpringSecurity | 3.2.7 |
Thymeleaf | 2.1.4 |
Doma | 1.0.38 |
Gradle | 2.3.10 |
æ§æ
build.gradle
buildscript { ext { springBootVersion = '1.2.4.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") classpath("io.spring.gradle:dependency-management-plugin:0.5.1.RELEASE") } } apply plugin: 'java' apply plugin: 'eclipse-wtp' apply plugin: 'idea' apply plugin: 'spring-boot' apply plugin: 'io.spring.dependency-management' apply plugin: 'war' war { baseName = 'demo' version = '1.0' } sourceCompatibility = 1.7 targetCompatibility = 1.7 // for Doma // Javaã¯ã©ã¹ã¨SQLãã¡ã¤ã«ã®åºåå ãã£ã¬ã¯ããªãåãã«ãã processResources.destinationDir = compileJava.destinationDir // ã³ã³ãã¤ã«ããåã«SQLãã¡ã¤ã«ãåºåå ãã£ã¬ã¯ããªã«ã³ãã¼ããããã«ä¾åé¢ä¿ãé転ãã compileJava.dependsOn processResources repositories { maven {url 'http://maven.seasar.org/maven2'} mavenCentral() } configurations { providedRuntime } dependencies { compile("org.springframework.boot:spring-boot-starter-aop") // SpringSecurityã®ä¾å compile("org.springframework.boot:spring-boot-starter-security") compile("org.springframework.boot:spring-boot-starter-thymeleaf") compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-jdbc") // htmlã§Thymeleafç¨ã®SpringSecurityã¿ã°ä½¿ãããã®ãã® compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity3") compile("org.hibernate:hibernate-validator") compile("org.seasar.doma:doma:1.38.0") compile("org.projectlombok:lombok:1.16.4") compile files("C:/app/lib/jdbc/ojdbc7.jar") providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") } eclipse { classpath { containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7' } } task wrapper(type: Wrapper) { gradleVersion = '2.3' }
demo/SecurityConfig.java
package demo; 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.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.web.util.matcher.AntPathRequestMatcher; import demo.impl.AuthenticationProviderImpl; import demo.impl.UserDetailsServiceImpl; @Configuration @EnableWebMvcSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsServiceImpl userDetailsService; @Autowired private AuthenticationProviderImpl authenticationProvider; @Override protected void configure(HttpSecurity http) throws Exception { http .headers() .xssProtection() .frameOptions() .contentTypeOptions() .cacheControl() .and() .authorizeRequests() // èªè¨¼å¯¾è±¡å¤ã®ãã¹ãè¨å®ãã .antMatchers("/", "/login", "/registration/**", "/css/**", "/js/**", "/img/**") // ä¸è¨ãã¹ã¸ã®ã¢ã¯ã»ã¹ã許å¯ãã .permitAll() // ãã®ä»ã®ãªã¯ã¨ã¹ãã¯èªè¨¼ãå¿ è¦ .anyRequest().authenticated() .and() .formLogin() // ãã°ã¤ã³ãã©ã¼ã ã®ãã¹ .loginPage("/") // ãã°ã¤ã³å¦çã®ãã¹ .loginProcessingUrl("/login") // ãã°ã¤ã³æåæã®é·ç§»å .defaultSuccessUrl("/menu") // ãã°ã¤ã³å¤±ææã®é·ç§»å .failureUrl("/login-error") // ãã°ã¤ã³ãã©ã¼ã ã§ä½¿ç¨ããã¦ã¼ã¶ã¼åã®input name .usernameParameter("empNo") // ãã°ã¤ã³ãã©ã¼ã ã§ä½¿ç¨ãããã¹ã¯ã¼ãã®input name .passwordParameter("password") .permitAll() .and() .rememberMe() .tokenValiditySeconds(86400) // 1ã¶æï¼ç§ï¼ .and() .logout() // ãã°ã¢ã¦ãããã¹(GET)ã®å ´åè¨å®ããï¼CSRF対å¿ï¼ .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) // ãã°ã¢ã¦ããPOSTã®å ´åè¨å®ãã //.logoutUrl("/logout") // ãã°ã¢ã¦ãå¾ã®é·ç§»å .logoutSuccessUrl("/") // ã»ãã·ã§ã³ãç ´æ£ãã .invalidateHttpSession(true) // ãã°ã¢ã¦ãæã«åé¤ããã¯ããã¼å .deleteCookies("JSESSIONID", "remember-me") .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // ç¬èªèªè¨¼ã¯ã©ã¹ãè¨å®ãã auth .authenticationProvider(authenticationProvider) .userDetailsService(userDetailsService); } }
demo/dto/LoginUser.java
package demo.dto import java.util.ArrayList; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; import demo.entity.Emp; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class LoginUser extends User { private static final long serialVersionUID = 1L; // 追å ããï¼ãã¼ãã«ã§ã¦ã¼ã¶ã¼ã®ãã¼ã¨ãªãå¤ãè¨å®ããï¼ public String username; // 追å ãã public String password; // ç¬èªã§å¿ è¦ãªé ç® public String empNm; public LoginUser(Emp emp) { super(emp.empNo, emp.password, true, true, true, true, new ArrayList<GrantedAuthority>()); username = emp.empNo; password = emp.password; empNm = emp.empNm; } }
demo/impl/AuthenticationProviderImpl.java
package demo.impl; 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 demo.dao.EmpDao; import demo.entity.Emp; @Component public class AuthenticationProviderImpl implements AuthenticationProvider { private static final Logger log = LoggerFactory.getLogger(AuthenticationProviderImpl.class); @Autowired private EmpDao empDao; @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("ãã°ã¤ã³æ å ±ã«ä¸åãããã¾ãã"); } Emp emp = empDao.authEmp(id, password); if (emp == null) { // ä¾å¤ã¯SpringSecurityã«ãã£ããã®ãé©å½ã«ä½¿ç¨ throw new AuthenticationCredentialsNotFoundException("ãã°ã¤ã³æ å ±ãåå¨ãã¾ããã"); } return new UsernamePasswordAuthenticationToken(new LoginUser(emp), password, auth.getAuthorities()); } @Override public boolean supports(Class<?> token) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(token); } }
demo/impl/UserDetailsServiceImpl.java
package demo.impl; 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 demo.dao.EmpDao; import demo.dto.LoginUser; import demo.entity.Emp; @Component public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private EmpDao empDao; @Override public UserDetails loadUserByUsername(String empNo) throws UsernameNotFoundException { Emp emp = empDao.findByNo(empNo); if (emp == null) { throw new UsernameNotFoundException("ã¦ã¼ã¶ã¼ãè¦ã¤ããã¾ããã§ããã"); } return new LoginUser(emp); } }
demo/web/LoginController.java
package demo.web; import javax.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.RequestMapping; import demo.form.LoginForm; @Controller public class LoginController { @RequestMapping(value = "/") public String index(Model model) { model.addAttribute(new LoginForm()); return "login/login"; } /* ãã°ã¤ã³å¦çã¯å®è£ ããªããSpringSecurityã®å¦çã§è¡ãããã @RequestMapping(value = "/login") public String login(@Valid LoginForm form, BindingResult result, Model model) { if (result.hasErrors()) { return "login/login"; } return "redirect:/menu"; } */ // SpringConfigã§è¨å®ãããã°ã¤ã³ã§ããªãã£ãå ´åã®å¦çãå®ç¾©ãã @RequestMapping(value = "/login-error") public String loginError(Model model) { model.addAttribute("loginError", true); return "login/login"; } }
demo/web/MenuController.java
package demo.web; import org.springframework.security.web.bind.annotation.AuthenticationPrincipal; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import demo.dto.LoginUser; @Controller public class MenuController { @RequestMapping(value = "/menu") public String index(@AuthenticationPrincipal LoginUser loginUser, Model model) { // @AuthenticationPrincipalã使ãã¨èªè¨¼ãªãã¸ã§ã¯ããåç §ã§ããã return "menu/menu"; } }
templates/login.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> </head> <body> <h1>login</h1> <!-- ãã°ã¤ã³ã§ããªãã£ãæã®ã¨ã©ã¼ã¡ãã»ã¼ã¸ --> <p th:if="${loginError}">Login Error!!</p> <form th:action="@{/login}" method="post"> <table> <tr> <td>社å¡çªå·</td> <td> <input type="text" name="empNo" /> </td> </tr> <tr> <td>ãã¹ã¯ã¼ã</td> <td> <input type="password" name="password" /> </td> </tr> </table> <input name="remember-me" type="checkbox" />ãã°ã¤ã³ããã¾ã¾ã«ãã <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" /> <input type="submit" name="login" value="ãã°ã¤ã³" /> </form> </body> </html>
templates/menu.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> </head> <body> <h1>menu</h1> <!-- èªè¨¼ããã¦ããã --> <p th:if="${#authorization.expression('isAuthenticated()')}">èªè¨¼æ¸ã¿</p> <!-- èªè¨¼ãªãã¸ã§ã¯ãã®åç § --> <p th:text="${#authentication.principal.empNm}"></p> </body> </html>
Springé¢é£æ¬
ã¯ããã¦ã®Spring BootâãSpring Frameworkãã§ç°¡åJavaã¢ããªéçº (Iã»O BOOKS)
- ä½è : æ§ä¿æ
- åºç社/ã¡ã¼ã«ã¼: å·¥å¦ç¤¾
- çºå£²æ¥: 2014/11
- ã¡ãã£ã¢: åè¡æ¬
- ãã®ååãå«ãããã° (8件) ãè¦ã
SpringFramework4ããã°ã©ãã³ã°å ¥é
- ä½è : æç°æ´¥è¶ä¹
- åºç社/ã¡ã¼ã«ã¼: ç§åã·ã¹ãã
- çºå£²æ¥: 2014/07/30
- ã¡ãã£ã¢: åè¡æ¬
- ãã®ååãå«ãããã° (2件) ãè¦ã