在自定义UserDetailsS​​ervice

时间:2020-11-12 12:59:21

标签: spring spring-boot spring-security spring-oauth2

我正在使用 Spring Boot OAuth授权服务器旧堆栈),并使用Oauth2实现自己的ClientDetailsServiceUserDetailsService版本password流。

我们的JpaClientDetailsService实现loadClientByClientId并返回ClientDetails,其中包含正在认证的客户端的详细信息。

@Service
public class JpaClientDetailsService implements ClientDetailsService {

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
    
        BaseClientDetails baseClientDetails = new BaseClientDetails(...);

        //do processing....

        return baseClientDetails;

    }

}

此后,我们实现loadUserByUsername的方法JpaUserDetailsService被调用,接收试图进行身份验证的用户的用户名:

@Service
public class JpaUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        return null;

    }

}

我的问题是: 我如何访问ClientDetails内部JpaClientDetailsService.loadClientByClientId返回的当前JpaUserDetailsService.loadUserByUsername

谢谢!

1 个答案:

答案 0 :(得分:0)

我意识到SecurityContextHolder.getContext().getAuthentication()包含有关正在认证的client的信息。因此,我能够获得client的名称并按如下方式加载其数据:

@Service
public class JpaUserDetailsService implements UserDetailsService {

    @Autowired
    private OAuthClientsRepository oAuthClientsRepository;

    @Override
    public org.springframework.security.core.userdetails.UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //Gets the Authentication from SecurityContextHolder
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        
        //ClientId is 'Principal's' Username
        var clientId = ((User) authentication.getPrincipal()).getUsername();

        //Gets clientDetails from JPA Repository. This would execute another Roundtrip to Database, but since we have 2nd level cache configured, this
        //problema is minimized.
        ClientDetails authClient = oAuthClientsRepository
                .findByClientId(clientId)
                .orElseThrow(() -> new NoSuchClientException(String.format("ClientId '%s' not found", clientId)));

        //....

    }

}

就是这样。