Remember-Me のログイン時のパラメータの謎について追う
Remember-Me 認証でログインするときに、フォームには <input type="checkbox" name="remember-me" />
を追加しておけばいい。
けど、 value
属性を省略した場合って、なんの値が渡っているのだろう?
実際に動かしたら、 on
という値が渡っていた。
<input type="checkbox"> - HTML | MDN
value
(略)省略された場合は、要素の value プロパティの取得結果は文字列の “on” になります。
一応 value
を省略したら on
がデフォルトになるらしい。
でも、携帯とかだと機種によって値が違う みたいな情報もあった。
Spring Security はどうやって値を取得しているのだろう?
ログイン時に Remember-Me を有効にするかどうかを判定しているところを探す。
<remember-me>
タグの remember-me-parameter
属性でリクエストパラメータの値を変更できるので、これを使っているところを追えばおのずとログイン時の処理の場所を特定できそう。
spring-security-config-4.2.1.RELEASE.jar
の中を remember-me-parameter
で GREP 検索する(IntelliJ だと jar の中を GREP できるので便利)
RememberMeBeanDefinitionParser
というのが唯一引っ掛かった。
class RememberMeBeanDefinitionParser implements BeanDefinitionParser { ... static final String ATT_FORM_REMEMBERME_PARAMETER = "remember-me-parameter";
この定数を使っているところを追うと、同じクラスの以下の場所にたどり着いた。
if (remembermeParameterSet) { services.getPropertyValues().addPropertyValue("parameter", remembermeParameter); }
なんか、 services
の parameter
プロパティに設定している。
services
が何なのか上の方を辿ると、
if (isPersistent) { Object tokenRepo; services = new RootBeanDefinition( PersistentTokenBasedRememberMeServices.class); ... } else if (!servicesRefSet) { services = new RootBeanDefinition(TokenBasedRememberMeServices.class); }
となってた。
つまり、 PersistentTokenBasedRememberMeServices
か TokenBasedRememberMeServices
ということになる。
共通の親クラスである AbstractRememberMeServices
を見ると、 parameter
がいた。
public abstract class AbstractRememberMeServices implements RememberMeServices, ... public static final String DEFAULT_PARAMETER = "remember-me"; ... private String parameter = DEFAULT_PARAMETER;
間違いなさそう。
この parameter
を使ってる場所を見てみる。
public final void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { if (!rememberMeRequested(request, parameter)) { logger.debug("Remember-me login not requested."); return; } onLoginSuccess(request, response, successfulAuthentication); }
rememberMeRequested(request, parameter)
ってところが、完全に Remember-Me を有効にすべきかどうか判定しているっぽい。
false
なら何もせずに return
し、 true
なら onLoginSuccess()
呼んでるので、おそらく間違いない。
rememberMeRequested()
を見てみる。
protected boolean rememberMeRequested(HttpServletRequest request, String parameter) { if (alwaysRemember) { return true; } String paramValue = request.getParameter(parameter); if (paramValue != null) { if (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on") || paramValue.equalsIgnoreCase("yes") || paramValue.equals("1")) { return true; } } if (logger.isDebugEnabled()) { logger.debug("Did not send remember-me cookie (principal did not set parameter '" + parameter + "')"); } return false; }
泥臭いことしてた!