SpringSecurityでログイン中のユーザー情報を更新してみる!

Spring Securityを使っていてログイン中のユーザー情報を変更する機能ってあるじゃないですか。そうするときにどうするのか気になりまして。

SecurityContextを更新すれば良さそう

結論としてはSecurityContextのAuthenticationを更新すれば良さそうです。以下のstackoverflowの質問と回答が役に立ちました。

https://stackoverflow.com/questions/7889660/how-to-reload-spring-security-principal-after-updating-in-hibernate

SecurityContextっていうのはログイン中のユーザー情報を保持するクラスでセッションごとに値を持っています。値もデフォルトの設定ではセッション似保存されるので、単にDBだけを更新したとしてもSecurityContextは更新されません。そこでSecurityContextも合わせて更新させないとおかしなことになってしまうということですね。

更新のやり方は色々とあるかと思いますが、 User クラスを UserDetailsService から返している場合にはこうなるんじゃないかなと。あくまでも一例になりますが。ここで UserEntity というクラスがありますがこれはDBのテーブルと対応したクラスです。

private void updateSecurityContext(UserEntity userEntity) {
    UserDetails user = User.builder()
            .username(userEntity.getUsername())
            .password(userEntity.getPassword())
            .roles(userMapper.findRolesByUserId(userEntity.getId()).toArray(String[]::new))
            .build();
    SecurityContext context = SecurityContextHolder.getContext();
    context.setAuthentication(new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()));
                                                                                                                        
    logger.info("security context updated to {}", user);
}

ソースコードの全量はこちら。

github.com