具有 OAuth2-ResourceServer 的 Spring 微服务仅返回 String 作为主体而不是我的自定义用户

Posted

技术标签:

【中文标题】具有 OAuth2-ResourceServer 的 Spring 微服务仅返回 String 作为主体而不是我的自定义用户【英文标题】:Spring microservices with OAuth2- ResourceServer returns only String as principal not my custom user 【发布时间】:2018-12-04 09:24:50 【问题描述】:

我有两个微服务,一个配置为 OAuth2 服务器 - A,另一个配置为 OAuth2 客户端 - B。我想在这两个微服务之间共享我的自定义用户。当用户通过AI对自己进行身份验证时,创建UserDetails的自定义实现,我想保护B中的一些资源。所以我配置了与A相同的资源服务器。我希望我可以在之间共享我的UserDetails自定义实现A 和 B 使用 Principal。我能够从 A 中的主体获取自定义用户,但在 B 中,主体仅由字符串(用户名)表示。如何让资源服务器返回 UserDetails 的自定义实现而不仅仅是用户名?

source of A - server

服务器配置:

@SpringBootApplication
@EnableResourceServer
@EnableAuthorizationServer
@EnableWebSecurity
public class Application 
    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

UserDetailsS​​ervice 的实现,它返回我的实现 UserDetails 的 CustomUser(为简单起见只是一个虚拟的)

@Service
@Primary
public class UserDetailsServiceImpl implements UserDetailsService 
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        GrantedAuthority authority = new Authority("USER");
        return new CustomUser(5L, "username", "nooppassword", Arrays.asList(authority));
    

OAuth2服务器配置:

@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter 

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
        endpoints.authenticationManager(authenticationManager)
                 .tokenStore(tokenStore());
    

    @Bean
    public TokenStore tokenStore() 
        return new InMemoryTokenStore();
    

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
        clients.inMemory()
               .withClient("user")
               .secret("nooppassword")
               .authorizedGrantTypes("password", "refresh_token")
               .scopes("webapp");
    

WebSecurityConfigurerAdapter:

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter 

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception 
        return super.authenticationManagerBean();
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(userDetailsService);
    

这是其他服务“应该”通过仅返回 Principal 的 rest 端点访问主体的方式,在服务 A 中,它包含 CustomUser 的实例:

@RestController
@RequestMapping("/user")
public class UserRestController 

    @GetMapping("/auth")
    public Principal getPrincipal(Principal principal) 
        return principal;
    

客户 source of B - client

Application.properties - A 端点的 url

server.port=8081
security.oauth2.resource.user-info-uri=http://localhost:8080/user/auth

B的开始

@SpringBootApplication
@EnableResourceServer
@EnableWebSecurity
@EnableOAuth2Client
public class Application 
    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

最后是我用来测试主体是字符串(用户名)还是自定义用户的其余控制器。不幸的是,Principal 总是只包含一个用户名和字段映射,其中包含来自自定义用户的值。

@RestController
@RequestMapping("/client")
public class ClientRestController 

    @GetMapping("/print")
    public void printId(Principal principal) 
        System.out.println(principal);
    

你能帮我解决一下吗?如何通过我的 CustomUser 传递 Principal?

感谢您的帮助:)

【问题讨论】:

如果您的授权和资源服务器彼此不同,那么这个答案可能会对您有所帮助***.com/questions/51240197/… 【参考方案1】:

嗯,返回 Principal 对象不是一个好主意(很可能是它的实现类UsernamePasswordAuthenticationToken)。如果您只希望端点共享自定义用户详细信息,那么最好的方法是创建一个仅包含您想要公开的信息的数据传输对象。

获取委托人(发出请求的经过身份验证的用户)的推荐方法是从安全上下文中获取。更多信息请访问here。

【讨论】:

以上是关于具有 OAuth2-ResourceServer 的 Spring 微服务仅返回 String 作为主体而不是我的自定义用户的主要内容,如果未能解决你的问题,请参考以下文章

如果具有 ID 的元素具有类 [重复]

具有透明背景的 UITableView 具有纯黑色边框

编写一个Car类,具有String类型的属性品牌,具有功能drive;

具有多个视图的 UIScrollView(具有按钮、滚动视图和标签)

如何使用 ZIO(具有持久层)创建具有“传统”接口的小型库

sharepoint 是不是具有逐项权限,就像它具有逐项权限一样