在自定义UserDetailsS​​ervice

问题描述

我正在使用 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

谢谢!

解决方法

我意识到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)));

        //....

    }

}

就是这样。