Spring Security は複雑で、内部の挙動が読めないので、頑張って自分でやるのではなく、 現在の単純な ID と Password の仕組みをほぼそのまま利用することにした。
おそらく、第3の情報としては特に機密情報ではなく、そのユーザーが所属する何かの組織情報と想定できる。 なので、この情報と ID をまとめてしまって管理するということにする。
そうするとカスタマイズする部分は入り口だけでよく、後は既存の動きを利用できる。
ID と Password を使った認証はわかったが、それに加えて別のパラメータを追加した場合はどう処理する?。 パラメータが2個ではなく3個とか4個になった場合にどうするという話。
まずログインの認証リクエストの処理は AuthenticationFilter という部分を通る。
なのでこいつをカスタムしてやればよいのでは。
このようなインターフェーになっている
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter{ @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { } }
つまり request 渡すから勝手にやってくれ。
認証にはいくつか段階があるようだが、最初の段階では、外部からのパラメータを認証に使える状態に整形することと、静的な Validation を行うことが主のようだ。
ということでフィルターは何種類かあって何段にも出来るっぽい。
このフィルター間での情報の受け渡しには UsernamePasswordAuthenticationToken と呼ばれるものを使う。
次に AuthenticationProvider というモノが駆動する。 ここで、入ってきたパラメータと内部のデータベースとかに入っているであろう認証情報を突き合わせることで、可否を決める。
こんな感じになる
public class CustomAuthenticationProvider implements AuthenticationProvider{ @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { Account a = (Account)auth.getPrincipal(); String password = (String)auth.getCredentials(); // ここで認証とロールの付与 Collection<GrantedAuthority> authorityList = new ArrayList<>(); authorityList.add(new SimpleGrantedAuthority(a.getRoleAsEnum().getName())); return new UsernamePasswordAuthenticationToken(a, password, authorityList); } @Override public boolean supports(Class<?> authentication) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); } }