簡體   English   中英

帶有OAuth2- ResourceServer的Spring微服務僅以String作為主體而不是我的自定義用戶返回

[英]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的自定義實現,而不僅僅是用戶名?

A的來源-服務器

服務器配置:

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

UserDetailsS​​ervice的實現返回我的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;
    }
}

B的客戶來源-客戶

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM