[英]Spring microservices with OAuth2- ResourceServer returns only String as principal not my custom user
我有兩個微服務,一個配置為OAuth2服務器-A,另一個配置為OAuth2客戶端-B。我想在這兩個微服務之間共享我的自定義用戶。 當用戶通過AI進行身份驗證時,創建UserDetails的自定義實現,我想保護B中的某些資源。因此,我配置了與A相同的資源服務器。我希望可以在以下兩者之間共享UserDetails的自定義實現A和B使用主體。 我能夠從A中的主體獲取自定義用戶,但在B中,主體僅由String(username)表示。 如何使資源服務器返回UserDetails的自定義實現,而不僅僅是用戶名?
服務器配置:
@SpringBootApplication
@EnableResourceServer
@EnableAuthorizationServer
@EnableWebSecurity
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
UserDetailsService的實現返回我的CustomUser,該CustomUser實現了UserDetails(為簡單起見,只是一個虛擬對象)
@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");
}
}
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);
}
}
這是主體“應該”通過其余端點(僅返回主體)在其他服務中“應”訪問的方式,這里服務A中包含CustomUser的實例:
@RestController
@RequestMapping("/user")
public class UserRestController {
@GetMapping("/auth")
public Principal getPrincipal(Principal principal) {
return principal;
}
}
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);
}
}
最后是我用來測試主體是string(username)還是CustomUser的rest控制器。 不幸的是,主體始終僅包含用戶名和具有來自自定義用戶的值的字段映射。
@RestController
@RequestMapping("/client")
public class ClientRestController {
@GetMapping("/print")
public void printId(Principal principal) {
System.out.println(principal);
}
}
你能幫我解決嗎? 如何通過我的CustomUser傳遞Principal?
感謝幫助:)
好吧,返回Principal對象不是一個好主意(很可能是它的實現類UsernamePasswordAuthenticationToken
)。 如果您只希望端點共享自定義用戶詳細信息,那么最好的方法是創建一個僅包含您要公開的信息的數據傳輸對象。
推薦的獲取主體(正在發出請求的經過身份驗證的用戶)的方法是從安全上下文中獲取。 有關此的更多信息,請參見此處 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.