Spring Boot ã§æ¸ç±ã®è²¸åºç¶æ³ç¢ºèªã»è²¸åºç³è«ãã Web ã¢ããªã±ã¼ã·ã§ã³ãä½ã ( ãã®ï¼ï¼ )( ãã°ã¤ã³ç»é¢ã®ä½æï¼ )
æ¦è¦
Spring Boot ã§æ¸ç±ã®è²¸åºç¶æ³ç¢ºèªã»è²¸åºç³è«ãã Web ã¢ããªã±ã¼ã·ã§ã³ãä½ã ( ãã®ï¼ï¼ )( ãã°ã¤ã³ç»é¢ã®ä½æï¼ ) ã®ç¶ãã§ãã
- ä»åã®æé ã§ç¢ºèªã§ããã®ã¯ä»¥ä¸ã®å
容ã§ãã
- ã次åããèªåçã«ãã°ã¤ã³ãããæ©è½ã®ä½æ
åç §ãããµã¤ãã»æ¸ç±
-
Spring Security 3.1
- ä½è : Robert Winch
- åºç社/ã¡ã¼ã«ã¼: Packt Publishing
- çºå£²æ¥: 2012/12/26
- ã¡ãã£ã¢: ãã¼ãã¼ããã¯
- ãã®ååãå«ãããã°ãè¦ã
- ãChapter 6: Remember-me Servicesããåç §ãã¾ããã
Remember-Me Authentication
http://docs.spring.io/spring-security/site/docs/3.2.7.RELEASE/reference/htmlsingle/#remember-me- Spring Security ã®å ¬å¼ããã¥ã¢ã«ã§ãã
Spring Boot Security Application
http://kielczewski.eu/2014/12/spring-boot-security-application/- Spring Boot + Spring Security 㧠Remember-me æ©è½ãå®è£ ããæ¹æ³ãåèã«ãã¾ããã
How to achieve conditional resource import in a Spring XML context?
http://stackoverflow.com/questions/3035630/how-to-achieve-conditional-resource-import-in-a-spring-xml-context- applicationContext.xml ã®ä¸ã®è¨å®ã spring.profiles.active ã®å¤ã«ããå¤ããæ¹æ³ã調æ»ããæã«åç §ãã¾ããã
ç®æ¬¡
- ã¯ããã«
- 1.0.x-make-rememberme ãã©ã³ãã®ä½æ
- ãã°ã¤ã³ç»é¢ã«ã次åããèªåçã«ãã°ã¤ã³ããããã§ãã¯ããã¯ã¹ã追å ãã
- UserInfoUserDetails ã¯ã©ã¹ãloginsuccess.htmlãUserInfoDao ã¯ã©ã¹ãUserInfoService ã¯ã©ã¹ã®å¤æ´
- WebSecurityConfig ã¯ã©ã¹ã®å¤æ´
- åä½ç¢ºèª
- commitãPushãPull Requestããã¼ã¸
- ã¡ã¢æ¸ã
æé
ã¯ããã«
Spring Security ã® Remember-me æ©è½ãå®è£ ãã¾ãã
Remember-me æ©è½ã¨ã¯ããã°ã¤ã³ãã¦ããªãç¶æ ã§èªè¨¼ãå¿ è¦ãªãã¼ã¸ã«ã¢ã¯ã»ã¹ããæã«ãã°ã¤ã³ç»é¢ã¸ãªãã¤ã¬ã¯ãããèªåãã°ã¤ã³ããæ©è½ã§ããããã°ã¤ã³ç»é¢ã«ã¢ã¯ã»ã¹ããæã«ã¯åã«ãã°ã¤ã³ç»é¢ã表示ãã¾ã ( èªåãã°ã¤ã³ã¯ãã¾ãã )ã
Remember-me æ©è½ã«ã¯ TokenBased 㨠PersistentTokenBased ã®ï¼ã¤ã®æ¹æ³ãããã¾ãããä»å対å¿ããã®ã¯ TokenBased ã®æ¹ã§ããTokenBased 㯠IDããã¹ã¯ã¼ããããã·ã¥åããæååã remember-me Cookie ã«ã»ãããã¦ãã©ã¦ã¶ã¸è¿ããããID ããã¹ã¯ã¼ãããã©ã¦ã¶ã«è¿ãã®ãé¿ãããå ´åã«ã¯ PersistentTokenBased ã§å®è£ ããå¿ è¦ãããã¾ããremember-me Cookie ã«ã»ããããæååã«ã¤ãã¦ã¯ 5.2. Simple Hash-Based Token Approach ã«è¨è¼ããã¦ãã¾ãã
1.0.x-make-rememberme ãã©ã³ãã®ä½æ
- IntelliJ IDEA 㧠1.0.x-make-rememberme ãã©ã³ããä½æãã¾ãã
ãã°ã¤ã³ç»é¢ã«ã次åããèªåçã«ãã°ã¤ã³ããããã§ãã¯ããã¯ã¹ã追å ãã
src/main/resources/templates ã®ä¸ã® login.html ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã以ä¸ã®ç»åã®ç»é¢ã«ãªãã¾ãã
UserInfoUserDetails ã¯ã©ã¹ãloginsuccess.htmlãUserInfoDao ã¯ã©ã¹ãUserInfoService ã¯ã©ã¹ã®å¤æ´
UserInfoUserDetails ã¯ã©ã¹ã® getUsername ã¡ã½ãããè¿ãå¤ã Remember-me æ©è½ãçæãã Token ã® username ã«ã»ããããããããèªåãã°ã¤ã³æã® ID ã«ä½¿ç¨ããã¾ããç¾å¨ã¯ user_info.username ã®å¤ãè¿ãã¦ãã¾ãããä»åä½æãã¦ãããã°ã¤ã³ç»é¢ã§ã¯ user_info.mail_address ã ID ã¨ãã¦ããã®ã§ãgetUsername ã¡ã½ãã㧠user_info.mail_address ã®å¤ãè¿ãããã«å¤æ´ãã¾ãã
ãã®å¤æ´ã«ä¼´ãä»ã«ãããã¤ãå¤æ´ããå¿ è¦ãããã¯ã©ã¹ãåºã¦ãã¾ãã®ã§ãä¸ç·ã«å¤æ´ãã¾ãã
src/main/java/ksbysample/webapp/lending/security ã®ä¸ã® UserInfoUserDetails.java ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
src/main/resources/templates ã®ä¸ã® loginsuccess.html ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
src/main/java/ksbysample/webapp/lending/dao ã®ä¸ã® UserInfoDao.java ã ãªã³ã¯å ã®å 容 ãå¤æ´ãã¾ãã
src/main/resources/META-INF/ksbysample/webapp/lending/dao/UserInfoDao ã®ä¸ã® initCntBadcredentialsByUsername.sql ãé¸æå¾ãSHIFT+F6 ãæ¼ã㦠Rename ãã¤ã¢ãã°ã表示ããinitCntBadcredentialsByMailAddress.sql ã«ãã¡ã¤ã«åãå¤æ´ãã¾ããå¤æ´å¾ããªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
src/main/java/ksbysample/webapp/lending/service ã®ä¸ã® UserInfoService.java ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
WebSecurityConfig ã¯ã©ã¹ã®å¤æ´
- src/main/java/ksbysample/webapp/lending/config ã®ä¸ã® WebSecurityConfig.java ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
åä½ç¢ºèª
Gradle projects View ãã bootRun ã¿ã¹ã¯ãå®è¡ã㦠Tomcat ãèµ·åãã¾ãã
ã¾ã㯠remember-me Cookie ããªãç¶æ ã§èªè¨¼ãå¿ è¦ãªãã¼ã¸ã«ã¢ã¯ã»ã¹ãã¦ããã°ã¤ã³ç»é¢ã«æ»ããã¨ã確èªãã¾ãã
ãã©ã¦ã¶ãèµ·åã㦠http://localhost:8080/loginsuccess ã«ã¢ã¯ã»ã¹ãã¾ããããã°ã¤ã³æåï¼ãã®ç»é¢ã¯è¡¨ç¤ºããããã°ã¤ã³ç»é¢ã表示ããã¾ãã
ID ã« "[email protected]"ãPassword ã« "taro" ãå ¥åãã¦ãã次åããèªåçã«ãã°ã¤ã³ãããããã§ãã¯ããã«ããã°ã¤ã³ããã¿ã³ãã¯ãªãã¯ãã¾ããããã°ã¤ã³æåï¼ãã®ç»é¢ã表示ããã¾ãã
ãã©ã¦ã¶ãï¼åº¦çµäºããã¦ããèµ·åãç´ãã¾ããèµ·åããå¾ãhttp://localhost:8080/loginsuccess ã«ã¢ã¯ã»ã¹ããã¨ãã°ã¤ã³ç»é¢ã表示ããã¾ãã
次㯠remember-me Cookie ãããç¶æ ã§èªè¨¼ãå¿ è¦ãªãã¼ã¸ã«ã¢ã¯ã»ã¹ããã¨ããã°ã¤ã³ç»é¢ã«æ»ãããã®ãã¼ã¸ã表示ããããã¨ã確èªãã¾ãã
ID ã« "[email protected]"ãPassword ã« "taro" ãå ¥åãã¦ãä»åº¦ã¯ã次åããèªåçã«ãã°ã¤ã³ãããããã§ãã¯ãã¦ããã°ã¤ã³ããã¿ã³ãã¯ãªãã¯ãã¾ããããã°ã¤ã³æåï¼ãã®ç»é¢ã表示ããã¾ãã
å度ãã©ã¦ã¶ãï¼åº¦çµäºããã¦ããèµ·åãç´ãã¾ããèµ·åããå¾ãhttp://localhost:8080/loginsuccess ã«ã¢ã¯ã»ã¹ããã¨ä»åº¦ã¯ããã°ã¤ã³æåï¼ãã®ç»é¢ã表示ããã¾ãã
æå¾ã«ãã°ã¢ã¦ãæ©è½ã§ remember-me Cookie ãåé¤ããã¨ãæåã¨åãããã«èªè¨¼ãå¿ è¦ãªãã¼ã¸ã«ã¢ã¯ã»ã¹ãã¦ããã°ã¤ã³ç»é¢ã«æ»ããã¨ã確èªãã¾ãã
http://localhost:8080/logout ã«ã¢ã¯ã»ã¹ãã¦ãã°ã¢ã¦ããã¦ãã°ã¤ã³ç»é¢ã«æ»ãã¾ãã
å度ãã©ã¦ã¶ãï¼åº¦çµäºããã¦ããèµ·åãç´ãã¾ããèµ·åããå¾ãhttp://localhost:8080/loginsuccess ã«ã¢ã¯ã»ã¹ããã¨ä»åº¦ã¯ãã°ã¢ã¦ããããã¨ã«ãã remember-me Cookie ãåé¤ããã¦ããã®ã§ãã°ã¤ã³ç»é¢ã表示ããã¾ãã
Ctrl+F2 ãæ¼ã㦠Tomcat ãåæ¢ãã¾ãã
commitãPushãPull Requestããã¼ã¸
commit ãã¾ãããCode Analysisããã¤ã¢ãã°ãåºã¾ãããç¡è¦ãã¦ãCommitããã¿ã³ãã¯ãªãã¯ãã¾ãã
GitHub 㸠Pushã1.0.x-make-rememberme -> 1.0.x 㸠Pull Requestã1.0.x ã§ãã¼ã¸ã1.0.x-make-rememberme ãã©ã³ããåé¤ãããã¾ãã
ã¡ã¢æ¸ã
applicationContext.xml ã® id="txAdvice" ã® timeout ã 3ç§ã 㨠Debug æã«ã¿ã¤ã ã¢ã¦ããã¦ãã¾ã
ä»å Remember-me æ©è½ãå®è£ ãã¦ããæã«ãã¾ãåããªãã¨ããããã£ã¦ãããã°å®è¡ãã¦åä½ã確èªããã®ã§ãããapplicationContext.xml ã§ãã©ã³ã¶ã¯ã·ã§ã³ã®ã¿ã¤ã ã¢ã¦ãã 3ç§ã«è¨å®ãã¦ããããããããã°ä¸ã«ã¿ã¤ã ã¢ã¦ããçºçãã¦ã¾ã¨ãã«ãããã°ã§ãã¾ããã§ããããã
ã¿ã¤ã ã¢ã¦ãããã¨ç»é¢ã«ä»¥ä¸ã®ãããªã¨ã©ã¼ã¡ãã»ã¼ã¸ã表示ããã¾ãã
spring.profiles.active = product ã®æ㯠3ç§ã®è¨å®ã¨ããdevelop ã®æã¯ã¿ã¤ã ã¢ã¦ããªãã«ãããã®ã§ãè¨å®ããæ¹æ³ã調ã¹ã¾ããã
src/main/java/ksbysample/webapp/lending ã®ä¸ã® Application.java ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
src/main/resources ã®ä¸ã® applicationContext.xml ã®ãã¡ã¤ã«åã applicationContext-product.xml ã«å¤æ´ãã¾ãã
applicationContext-product.xml ãã³ãã¼ã㦠applicationContext-unittest.xml ãä½æãã¾ããä¸ã¯åãã§ãã
ä½æããã applicationContext-unittest.xml ãèªåã§éãã¾ãããç»é¢ä¸é¨ã«ãApplication context not configured for this fileãã®ã¡ãã»ã¼ã¸ã表示ããã¾ããå³ä¸ã«è¡¨ç¤ºããã¦ãããConfigure application contextããªã³ã¯ãã¯ãªãã¯ãã¾ãã
ãChoose Application Contextãã¦ã£ã³ãã¦ã表示ãããã®ã§ããSpring Application Contextãã¡ãã¥ã¼ãé¸æãã¾ããé¸æå¾å°ãæéãçµã¤ã¨ç»é¢ä¸é¨ã®ãApplication context not configured for this fileãã®ã¡ãã»ã¼ã¸ãæ¶ãã¾ãã
applicationContext-product.xml ãã³ãã¼ã㦠applicationContext-develop.xml ãä½æãã¾ããä½æå¾ããªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
ä½æããã applicationContext-develop.xml ãèªåã§éãã®ã§ãapplicationContext-unittest.xml ã®æã¨åæ§ã«å³ä¸ã«è¡¨ç¤ºããã¦ãããConfigure application contextããªã³ã¯ãã¯ãªãã¯ããå¾ããChoose Application Contextãã¦ã£ã³ãã¦ãããSpring Application Contextãã¡ãã¥ã¼ãé¸æãã¾ãã
ã¡ã¤ã³ã¡ãã¥ã¼ãããFileã->ãProject Structure...ããé¸æãã¦ãProject Structureããã¤ã¢ãã°ã表示ãã¾ããç»é¢å·¦å´ã§ãProject Settingsã->ãModulesããé¸æããç»é¢ä¸å¤®ã§ãksbysample-webapp-lendingã->ãSpring ããé¸æããã¨ãç»é¢å³å´ã« applicationContext-product.xml, applicationContext-unittest.xml, applicationContext-develop.xml ãç»é²ããã¦ãããã¨ã確èªã§ãã¾ãã
ãOKããã¿ã³ãã¯ãªãã¯ãã¦ãProject Structureããã¤ã¢ãã°ãéãã¾ãã
Tomcat ãæ£å¸¸ã«èµ·åãããã¨ã確èªãã¾ããGradle projects View ãã bootRun ã¿ã¹ã¯ãå®è¡ã㦠Tomcat ãèµ·åãã¾ãã
Tomcat ãæ£å¸¸ã«èµ·åããRun View ã«åºåããã¦ãããã°ãã applicationContext-develop.xml ã使ç¨ããã¦ãããã¨ã確èªã§ãã¾ãã
Ctrl+F2 ãæ¼ã㦠Tomcat ãåæ¢ãã¾ãã
ä»åã¯ãã®ã¾ã¾ commitãGitHub 㸠Push ãã¾ãã
ã½ã¼ã¹ã³ã¼ã
login.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>ãã°ã¤ã³ç»é¢</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <!-- Bootstrap 3.3.4 --> <link href="/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> <!-- Font Awesome Icons --> <link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css"/> <!-- Ionicons --> <link href="/css/ionicons.min.css" rel="stylesheet" type="text/css"/> <!-- Theme style --> <link href="/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/> <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. --> <link href="/css/skins/_all-skins.min.css" rel="stylesheet" type="text/css"/> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="/js/html5shiv.min.js"></script> <script src="/js/respond.min.js"></script> <![endif]--> <style> <!-- .content-wrapper { background-color: #fffafa; padding-top: 50px; } .form-group { margin-bottom: 5px; } --> </style> </head> <!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. --> <body class="skin-blue layout-top-nav"> <div class="wrapper"> <!-- Full Width Column --> <div class="content-wrapper"> <div class="container"> <!-- Main content --> <section class="content"> <div class="row"> <div class="col-xs-12 col-md-push-3 col-md-6"> <div class="form-wrap"> <div class="text-center"><h1>ksbysample-lending</h1></div> <br/> <form role="form" action="#" th:action="@{/login}" method="post" id="login-form" autocomplete="off"> <div class="form-group" th:if="${session['SPRING_SECURITY_LAST_EXCEPTION']} != null"> <p class="form-control-static text-danger" th:text="${session['SPRING_SECURITY_LAST_EXCEPTION'].message}"></p> </div> <div class="form-group"> <label for="id" class="sr-only">ID</label> <input type="text" name="id" id="id" class="form-control" placeholder="ID ãå ¥åãã¦ä¸ãã" th:value="${session['SPRING_SECURITY_LAST_EXCEPTION']} != null ? ${session['SPRING_SECURITY_LAST_EXCEPTION'].authentication.principal} : ''"/> </div> <div class="form-group"> <label for="password" class="sr-only">Password</label> <input type="password" name="password" id="password" class="form-control" placeholder="Password ãå ¥åãã¦ä¸ãã"/> </div> <div class="form-group text-center"> <div class="checkbox"> <label><input type="checkbox" name="remember-me" id="remember-me" value="true"/>次åããèªåçã«ãã°ã¤ã³ãã</label> </div> </div> <button id="btn-login" class="btn btn-primary btn-block">ãã°ã¤ã³</button> </form> </div> </div> </div> </section> <!-- /.content --> </div> <!-- /.container --> </div> </div> <!-- ./wrapper --> <!-- jQuery 2.1.4 --> <script src="/js/jQuery-2.1.4.min.js" type="text/javascript"></script> <!-- Bootstrap 3.3.2 JS --> <script src="/js/bootstrap.min.js" type="text/javascript"></script> <!-- AdminLTE App --> <script src="/js/app.min.js" type="text/javascript"></script> <script type="text/javascript"> <!-- $(document).ready(function() { $('#id').focus().select(); }); --> </script> </body> </html>
<div class="form-group text-center"> ... <label><input type="checkbox" name="remember-me" id="remember-me" value="true"/>次åããèªåçã«ãã°ã¤ã³ãã</label> ... </div>
ã®é¨åã追å ãã¾ãã- ãã§ãã¯ããã¯ã¹ã® name å±æ§ã®å¤ã¯
remember-me
ã«ãã¾ãããã®åå㯠org.springframework.security.config.annotation.web.configurers ããã±ã¼ã¸ã®ä¸ã® RememberMeConfigurer.java ã®ä¸ã§private String rememberMeParameter = "remember-me";
ã¨å®ç¾©ããã¦ãã¾ãã
UserInfoUserDetails.java
package ksbysample.webapp.lending.security; import ksbysample.webapp.lending.entity.UserInfo; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDateTime; import java.util.Collection; import java.util.Set; public class UserInfoUserDetails implements UserDetails { private UserInfo userInfo; private final Set<? extends GrantedAuthority> authorities; private final boolean accountNonExpired; private final boolean accountNonLocked; private final boolean credentialsNonExpired; private final boolean enabled; public UserInfoUserDetails(UserInfo userInfo , Set<? extends GrantedAuthority> authorities) { LocalDateTime now = LocalDateTime.now(); this.userInfo = userInfo; this.authorities = authorities; this.accountNonExpired = !userInfo.getExpiredAccount().isBefore(now); this.accountNonLocked = (userInfo.getCntBadcredentials() < 5); this.credentialsNonExpired = !userInfo.getExpiredPassword().isBefore(now); this.enabled = (userInfo.getEnabled() == 1); } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } @Override public String getPassword() { return userInfo.getPassword(); } @Override public String getUsername() { return userInfo.getMailAddress(); } public String getName() { return userInfo.getUsername(); } @Override public boolean isAccountNonExpired() { return accountNonExpired; } @Override public boolean isAccountNonLocked() { return accountNonLocked; } @Override public boolean isCredentialsNonExpired() { return credentialsNonExpired; } @Override public boolean isEnabled() { return enabled; } }
- getUsername ã¡ã½ãã㧠userInfo.getMailAddress() ãè¿ãããã«å¤æ´ãã¾ãã
- user_info.getUsername() ã®å¤ãè¿ãããã® getName ã¡ã½ããã追å ãã¾ãã
- userInfo.getMailAddress() ãè¿ãããã«ç¨æãã¦ãã getMailAddress ã¡ã½ããã¯åé¤ãã¾ãã
loginsuccess.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>ãã¹ãç¨ãã°ã¤ã³æåãã¼ã¸</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <!-- Bootstrap 3.3.4 --> <link href="/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> <!-- Font Awesome Icons --> <link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css"/> <!-- Ionicons --> <link href="/css/ionicons.min.css" rel="stylesheet" type="text/css"/> <!-- Theme style --> <link href="/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/> <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. --> <link href="/css/skins/_all-skins.min.css" rel="stylesheet" type="text/css"/> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="/js/html5shiv.min.js"></script> <script src="/js/respond.min.js"></script> <![endif]--> <style> <!-- .content-wrapper { background-color: #fffafa; padding-top: 50px; } .form-group { margin-bottom: 5px; } --> </style> </head> <!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. --> <body class="skin-blue layout-top-nav"> <div class="wrapper"> <!-- Full Width Column --> <div class="content-wrapper"> <div class="container"> <!-- Main content --> <section class="content"> ãã°ã¤ã³æåï¼<br/> ã¦ã¼ã¶å: <span sec:authentication="principal.name">Bob</span><br/> ã¡ã¼ã«ã¢ãã¬ã¹: <span sec:authentication="name">[email protected]</span><br/> Roles: <span sec:authentication="principal.authorities">[ROLE_USER, ROLE_ADMIN]</span><br/> <div sec:authorize="hasRole('ROLE_ADMIN')">ROLE_ADMIN ãä»ä¸ããã¦ãã¾ã</div> <div sec:authorize="hasRole('ROLE_APPROVER')">ROLE_APPROVER ãä»ä¸ããã¦ãã¾ã</div> <div sec:authorize="hasRole('ROLE_USER')">ROLE_USER ãä»ä¸ããã¦ãã¾ã</div> </section> <!-- /.content --> </div> <!-- /.container --> </div> </div> <!-- ./wrapper --> <!-- jQuery 2.1.4 --> <script src="/js/jQuery-2.1.4.min.js" type="text/javascript"></script> <!-- Bootstrap 3.3.2 JS --> <script src="/js/bootstrap.min.js" type="text/javascript"></script> <!-- AdminLTE App --> <script src="/js/app.min.js" type="text/javascript"></script> <script type="text/javascript"> <!-- --> </script> </body> </html>
ã¦ã¼ã¶å: <span sec:authentication="name">Bob</span><br/>
âã¦ã¼ã¶å: <span sec:authentication="principal.name">Bob</span><br/>
ã«å¤æ´ãã¾ããã¡ã¼ã«ã¢ãã¬ã¹: <span sec:authentication="principal.mailAddress">[email protected]</span><br/>
âã¡ã¼ã«ã¢ãã¬ã¹: <span sec:authentication="name">[email protected]</span><br/>
ã«å¤æ´ãã¾ãã
UserInfoDao.java
package ksbysample.webapp.lending.dao; import ksbysample.webapp.lending.entity.UserInfo; import ksbysample.webapp.lending.util.doma.ComponentAndAutowiredDomaConfig; import org.seasar.doma.Dao; import org.seasar.doma.Delete; import org.seasar.doma.Insert; import org.seasar.doma.Select; import org.seasar.doma.Update; /** */ @Dao @ComponentAndAutowiredDomaConfig public interface UserInfoDao { /** * @param userId * @return the UserInfo entity */ @Select UserInfo selectById(Long userId); @Select UserInfo selectByMailAddress(String mailAddress); /** * @param entity * @return affected rows */ @Insert int insert(UserInfo entity); /** * @param entity * @return affected rows */ @Update int update(UserInfo entity); @Update(sqlFile = true) int incCntBadcredentialsByMailAddress(String mailAddress); @Update(sqlFile = true) int initCntBadcredentialsByMailAddress(String mailAddress); /** * @param entity * @return affected rows */ @Delete int delete(UserInfo entity); }
int initCntBadcredentialsByUsername(String username);
âint initCntBadcredentialsByMailAddress(String mailAddress);
ã«å¤æ´ãã¾ãã
initCntBadcredentialsByMailAddress.sql
update user_info set cnt_badcredentials = 0 where mail_address = /* mailAddress */'[email protected]'
username = /* username */'tanaka taro'
âmail_address = /* mailAddress */'[email protected]'
ã¸å¤æ´ãã¾ãã
UserInfoService.java
package ksbysample.webapp.lending.service; import ksbysample.webapp.lending.dao.UserInfoDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserInfoService { @Autowired private UserInfoDao userInfoDao; public void incCntBadcredentials(String mailAddress) { userInfoDao.incCntBadcredentialsByMailAddress(mailAddress); } public void initCntBadcredentials(String mailAddress) { userInfoDao.initCntBadcredentialsByMailAddress(mailAddress); } }
- initCntBadcredentials ã¡ã½ããå
ã§å¼ã³åºãã¡ã½ããã
userInfoDao.initCntBadcredentialsByUsername
âuserInfoDao.initCntBadcredentialsByMailAddress
ã¸å¤æ´ãã¾ãã
WebSecurityConfig.java
package ksbysample.webapp.lending.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 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.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @SuppressWarnings("SpringJavaAutowiringInspection") @Autowired private UserDetailsService userDetailsService; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // èªè¨¼ã®å¯¾è±¡å¤ã«ãããURLãããå ´åã«ã¯ã以ä¸ã®ãããªè¨è¿°ã追å ãã¾ã // è¤æ°URLãããå ´åã¯antMatchersã¡ã½ããã«ã«ã³ãåºåãã§å¯¾è±¡URLãè¤æ°åæãã¾ã // .antMatchers("/country/**").permitAll() .antMatchers("/fonts/**").permitAll() .antMatchers("/html/**").permitAll() .antMatchers("/encode").permitAll() .anyRequest().authenticated(); http.formLogin() .loginPage("/") .loginProcessingUrl("/login") .defaultSuccessUrl("/loginsuccess") .usernameParameter("id") .failureUrl("/") .passwordParameter("password") .permitAll() .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/") .deleteCookies("JSESSIONID") .deleteCookies("remember-me") .invalidateHttpSession(true) .permitAll() .and() .rememberMe() .key("ksbysample-webapp-lending") .tokenValiditySeconds(60 * 60 * 24 * 30); } @Bean public AuthenticationProvider daoAuhthenticationProvider() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService); daoAuthenticationProvider.setHideUserNotFoundExceptions(false); daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder()); return daoAuthenticationProvider; } @Autowired public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(daoAuhthenticationProvider()) .userDetailsService(userDetailsService); } }
- configure ã¡ã½ããå
ã®å¦çã®ä»¥ä¸ã®ç¹ãå¤æ´ãã¾ãã
- logout æã®å¦çã«
.deleteCookies("remember-me")
ã追å ãã¾ãã .and().rememberMe() ... .tokenValiditySeconds(60 * 60 * 24 * 30);
ã追å ãã¾ããRemember-me æ©è½ãçæãã Token ã®æå¹æéã 30æ¥ã«ãã¾ãã
- logout æã®å¦çã«
- configAuthentication ã¡ã½ããå
ã®å¦çã«
.userDetailsService(userDetailsService)
ã追å ãã¾ãããã㯠Remember-me æ©è½ã UserDetailsService å¿ é ã®ãããAuthenticationProvider Bean ã§è¨å®ããã®ã¨ã¯å¥ã«è¨å®ããå¿ è¦ãããããã§ãã
Application.java
package ksbysample.webapp.lending; import org.apache.commons.lang3.StringUtils; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; import java.text.MessageFormat; @ImportResource("classpath:applicationContext-${spring.profiles.active}.xml") @SpringBootApplication public class Application { public static void main(String[] args) { String springProfilesActive = System.getProperty("spring.profiles.active"); if (!StringUtils.equals(springProfilesActive, "product") && !StringUtils.equals(springProfilesActive, "develop") && !StringUtils.equals(springProfilesActive, "unittest")) { throw new UnsupportedOperationException(MessageFormat.format("JVMã®èµ·åæå¼æ° -Dspring.profiles.active 㧠develop ã unittest ã product ãæå®ãã¦ä¸ãã ( -Dspring.profiles.active={0} )ã", springProfilesActive)); } SpringApplication.run(Application.class, args); } }
- @ImportResource ã¢ããã¼ã·ã§ã³ã®ä¸ã§æå®ãã xml ãã¡ã¤ã«åã
applicationContext.xml
âapplicationContext-${spring.profiles.active}.xml
ã¸å¤æ´ãã¾ãã
applicationContext-develop.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" rollback-for="Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pointcutService" expression="execution(* ksbysample.webapp.lending..*Service.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcutService"/> </aop:config> </beans>
<tx:method name="*" rollback-for="Exception" timeout="3"/>
â<tx:method name="*" rollback-for="Exception"/>
ã¸å¤æ´ãã¾ããtimeout ã®è¨å®ãåãé¤ãã¾ãã
å±¥æ´
2015/07/22
åççºè¡ã