当前位置: 首页 > 知识库问答 >
问题:

Spring microservices with OAuth2-ResourceServer只返回字符串作为主体,而不是我的自定义用户

长孙兴德
2023-03-14

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

A的源-服务器

服务器配置:

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

UserDetailsService的实现,它返回实现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", "{noop}password", 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("{noop}password")
               .authorizedGrantTypes("password", "refresh_token")
               .scopes("webapp");
    }
}

网络安全配置适配器:

@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);
    }
}

这是其他服务“应该”通过restendpoint访问主体的方式,restendpoint只返回主体,在服务A中,它包含CustomUser的实例

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

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

B的客户端源-客户端

应用properties-来自的终结点的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);
    }
}

最后是rest控制器,我用它来测试主体是string(username)还是CustomUser。不幸的是,主体始终只包含一个用户名和字段映射,其中包含来自自定义用户的值。

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

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

你能帮我解决这个问题吗?如何向我的CustomUser传递Principal?

谢谢你的帮助:)

共有1个答案

姚和顺
2023-03-14

好吧,返回主体对象不是一个好主意(很可能是它的实现类UsernamePasswordAuthentiationToken)。如果您只想让endpoint共享自定义用户详细信息,那么更可取的方法是创建一个数据搬迁对象,该对象仅包含您想公开的信息。

建议从安全上下文获取主体(发出请求的经过身份验证的用户)。有关这方面的更多信息,请参见此处。

 类似资料:
  • 以下endpoint以字符串形式返回用户名。 我如何构造它以返回一个json对象,该对象包含一个键,该键的值为该字符串(例如,{“user”:“joeuser”})?

  • 让我来解释一下这个问题。我使用node-mongoDB本地作为mongob驱动程序,每次我需要通过_id字段进行查找查询时,我必须将其转换为ObjectId,如下所示: 我不想对每一个请求都使用ObjectID。到目前为止,我找到的唯一解决方案是将自定义ObjectID生成为字符串,如下所示: 在本例中,我将_id作为字符串,不需要分别将其转换为ObjectID。但我不知道这将如何影响查询性能。

  • 问题内容: 我在做 是否可以将结果自动“解析”到“ POJO”列表? 这样我就可以做到这一点: 问题答案: 尝试 就像参考手册所建议的那样。

  • 字体始终显示默认字体。 我的字体存储在资源/字体中。我尝试使用其他字体,并对字体进行重新编码。此外,PixlUI库并没有解决这个问题。 主要活动。Java语言 activity\u main。xml

  • 问题内容: 我在做 是否可以将结果自动“解析”到“ POJO”列表? 这样我就可以做到这一点: 问题答案: 尝试 就像参考手册所建议的那样。

  • 问题内容: 我正在尝试使用Python 3的内置JSON模块进行一些简单的JSON解析,并且从阅读有关SO和谷歌搜索的其他问题来看,这似乎应该非常简单。但是,我想我得到的是返回的字符串,而不是预期的字典。 首先,这是我尝试从中获取值的JSON。这只是Twitter API的一些输出 我将此字符串分配给名为json_string的变量,如下所示: 然后,当我尝试从“杰森”字典中获取特定密钥时: 我收