如何配置必須使用“密碼”授權類型從授權服務器請求令牌的客戶端 Java 應用程序? (How do I configure a client Java application which must request a token from an authorization server using a 'password' grant type?)


問題描述

如何配置必須使用“密碼”授權類型從授權服務器請求令牌的客戶端 Java 應用程序? (How do I configure a client Java application which must request a token from an authorization server using a 'password' grant type?)

我需要使用 Maven 實現客戶端 Java 應用程序,該應用程序從資源服務器發出請求。為了授權請求,必須在請求的標頭中提供不記名令牌。要獲得令牌,必須先完成另一個請求。服務器為我提供了發出令牌請求所需的所有參數:client_id、client_secret、用戶名、密碼等。令牌請求的 grant_type 是“密碼”。

服務器基於 GraphQL,所以我' m 使用以下 Maven 插件來生成執行 GraphQL 查詢的 Java 類:https://github.com/graphql‑java‑generator/graphql‑maven‑plugin‑project

他們提供了有關如何“訪問 OAuth2 GraphQL 服務器”的教程:https://graphql‑maven‑plugin‑project.graphql‑java‑generator.com/client_oauth2.html

正如他們在教程中提到的,為了連接到OAuth 服務器,我必須使用 Spring。本教程解釋瞭如何訪問使用“client_credentials”授權類型的服務器。我不熟悉spring和spring‑security,所以我沒有設法將我的Spring客戶端配置為'password'授權類型(我所做的只是在application.properties中將grant_type從'client_credentials'更改為'password') . 需要在哪裡配置用戶名和密碼?我需要做哪些額外的配置?沒有春天有沒有辦法做到這一點?我想要獲得的是從授權服務器請求令牌並(在後台)將令牌添加到資源請求的方式。

以下是我遵循教程的一段代碼:

@SpringBootApplication(scanBasePackageClasses = { MinimalSpringApp.class, GraphQLConfiguration.class})
public class MinimalSpringApp implements CommandLineRunner
{
   /**
    * The executor, that allows to execute GraphQL queries. The class name is the one defined in the GraphQL schema.
    */
   @Autowired
   QueryExecutor queryExecutor;


   public static void main( String[] args )
   {
      SpringApplication.run( MinimalSpringApp.class, args );
   }


   /**
    * This method is started by Spring, once the Spring context has been loaded. This is run, as this class implements
    * {@link CommandLineRunner}
    */
   @Override
   public void run( String... args ) throws Exception
   {
// Create query
      GraphQLRequest softwareTechnologyRequest = queryExecutor.getSoftwareTechnologyGraphQLRequest( "{ id name }" );
      SoftwareTechnologyFilter filter = new SoftwareTechnologyFilter();

// Execute query
      List<SoftwareTechnology> technologies =
            queryExecutor.softwareTechnology( softwareTechnologyRequest, filter, 0, "", 1000, "", 0,
                  Collections.emptyList() );

      System.out.println( technologies );
   }

   @Bean
   ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction(
         ReactiveClientRegistrationRepository clientRegistrations) {
      ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
            clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
      oauth.setDefaultClientRegistrationId("provider_test");
      return oauth;
   }

當我運行應用程序時,它會拋出由“401 Unauthorized from POST”引起的 IllegalStateException。


參考解法

方法 1:

SOLVED

I needed to create my own client manager bean, where the username and password are set. There is an example in the Spring official documentation at the "Resource Owner Password Credentials" section: https://docs.spring.io/spring‑security/site/docs/5.2.0.RELEASE/reference/htmlsingle/#oauth2client

   @Bean
   public ReactiveOAuth2AuthorizedClientManager authorizedClientManager( ReactiveClientRegistrationRepository clientRegistrationRepository,
         ReactiveOAuth2AuthorizedClientService authorizedClientService)
   {
      ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
            ReactiveOAuth2AuthorizedClientProviderBuilder.builder().password().refreshToken().build();
      AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
            new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService );
      authorizedClientManager.setAuthorizedClientProvider( authorizedClientProvider );
      authorizedClientManager.setContextAttributesMapper( contextAttributesMapper() );
      return authorizedClientManager;
   }

   private Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>> contextAttributesMapper()
   {
      return authorizeRequest ‑> {
         Map<String, Object> contextAttributes = new HashMap<>();
         contextAttributes.put( OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username" );
         contextAttributes.put( OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password" );
         return Mono.just(contextAttributes);
      };
   }

Then the bean from the graphql java generator plugin tutorial needed to be adapted in order to use the provided client manager:

   @Bean
   ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction(
         ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
      ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
            authorizedClientManager);
      oauth.setDefaultClientRegistrationId("provider_test");
      return oauth;
   }

(by Ian ChelaruIan Chelaru)

參考文件

  1. How do I configure a client Java application which must request a token from an authorization server using a 'password' grant type? (CC BY‑SA 2.5/3.0/4.0)

#java #oauth-2.0 #maven #graphql #spring-boot






相關問題

電子郵件地址中帶有 + 字符的 Java 郵件 (Java mail with + character in email address)

如何快速原型化 Java 代碼? (How to quickly prototype Java code?)

如何使用 Maven 在目標(SVN-)服務器上創建 Javadoc? (How to create Javadoc on the target (SVN-) server using Maven?)

為什麼檢查二叉樹有效性的解決方案不起作用? (Why the solution for checking the validity of binary tree is not working?)

Selenium webdriver通過第一個數字找到texy (Selenium webdriver find texy by first digits)

setOnClickListener 沒有在圖像視圖上被調用 (setOnClickListener is not getting called on image view)

繪製多邊形:找不到錯誤 (Drawing Polygon : unable to find error)

半透明 JButton:對像出現在背景中 (Semi-Transparent JButton: Objects appear in Background)

比較同一數組的元素 (Compare elements of the same array)

Java 屏幕截圖小程序 (Java screen capture applet)

Minecraft 1.8.9 Forge Modding 的Java 開發工具包,需要什麼JDK/JRE,代碼是否正確? (Java Development Kit with Minecraft 1.8.9 Forge Modding, What JDK/JRE Is Needed, Is Code Correct?)

java while (resultset.next()) 不返回同一列中的所有數據 (java while (resultset.next()) does not return all data in the same column)







留言討論