首頁 >Java >java教程 >Java API 開發中使用 OAuth2 鑑權

Java API 開發中使用 OAuth2 鑑權

王林
王林原創
2023-06-18 11:49:371531瀏覽

在 Java API 的開發中,鑑權是不可避免的問題。 OAuth2 是一種流行的鑑權方式,它透過授權存取來保護 API 資源。本文將介紹如何在 Java API 開發中使用 OAuth2 進行鑑權。

OAuth2 簡介

OAuth2 是一種用於授權的開放標準,它允許使用者授權第三方應用程式存取他們的伺服器資源,而不必分享他們的憑證。 OAuth2 標準包括下列角色:

  • Resource Owner:資源擁有者,即使用者;
  • Resource Server:資源伺服器,提供資源的伺服器;
  • Client:客戶端,即第三方應用程式;
  • Authorization Server:授權伺服器,用於頒發存取權杖。

OAuth2 的授權程序包括以下步驟:

  • Client 向Authorization Server 發送授權請求;
  • Authorization Server 向Resource Owner 請求授權;
  • Resource Owner 授權後,Authorization Server 傳送存取權杖給Client;
  • Client 使用存取權杖向Resource Server 傳送請求;
  • Resource Server 驗證存取權杖並提供資源。

OAuth2 支援多種授權類型,包括授權碼模式、密碼模式、客戶端模式、隱含授權模式等。在 Java API 開發中,通常使用授權碼模式和密碼模式。

OAuth2 授權碼模式

授權碼模式是OAuth2 中最常用的授權類型,它包含以下步驟:

  • Client 向Authorization Server 發送授權請求,包括Client ID 和重定向URI;
  • Authorization Server 發送登入頁面給Resource Owner,要求Resource Owner 登入並授權;
  • Resource Owner 授權後,Authorization Server 向重定向URI 發送授權碼;
  • Client 使用授權碼向Authorization Server 發送請求,包括Client ID 和Client Secret;
  • Authorization Server 驗證Client ID 和Client Secret,如果正確,頒發存取權令牌給Client;
  • Client 使用存取權杖向Resource Server 傳送請求。

在 Java API 開發中,可以使用 Spring Security OAuth2 框架實作授權碼模式的識別碼。

首先,需要在pom.xml 檔案中新增以下相依性:

<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.3.4.RELEASE</version>
</dependency>

然後,在Spring MVC 的設定檔中新增以下設定:

<security:http pattern="/oauth/token" create-session="stateless"
    authentication-manager-ref="authenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <security:intercept-url pattern="/oauth/token" access="isAuthenticated()" method="POST" />
    <security:anonymous enabled="false" />
    <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <security:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
    <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

<security:http pattern="/api/**" create-session="never"
    entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager"
    xmlns="http://www.springframework.org/schema/security">
    <security:anonymous enabled="false" />
    <security:intercept-url pattern="/api/**" access="ROLE_USER" />
    <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

<bean id="clientAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="spring-boot-oauth2" />
    <property name="typeName" value="Basic" />
</bean>

<bean id="oauthAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="spring-boot-oauth2" />
    <property name="typeName" value="Bearer" />
</bean>

<bean id="oauthAccessDeniedHandler"
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

<bean id="clientCredentialsTokenEndpointFilter"
    class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<bean id="resourceServerFilter"
    class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<bean id="accessDecisionManager"
    class="org.springframework.security.access.vote.UnanimousBased"
    xmlns="http://www.springframework.org/schema/beans">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
            <bean class="org.springframework.security.access.vote.RoleVoter" />
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
        </list>
    </constructor-arg>
</bean>

<security:authentication-manager id="authenticationManager">
    <security:authentication-provider user-service-ref="userDetailsService" />
</security:authentication-manager>

<bean id="userDetailsService"
    class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
    <property name="dataSource" ref="dataSource" />
</bean>

其中,/ oauth/token 是用來取得存取權杖的路徑,/api/** 是需要進行鑑權的路徑。

使用 OAuth2RestTemplate 發送請求時,需要先取得存取權杖,程式碼如下:

OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(client, context);
AuthorizationCodeResourceDetails details = (AuthorizationCodeResourceDetails)client.getResource();
AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider();
Authentication auth = new UsernamePasswordAuthenticationToken(username, password);
AccessTokenRequest tokenRequest = provider.createAccessTokenRequest(details, auth);
OAuth2AccessToken accessToken = provider.obtainAccessToken(details, tokenRequest);
restTemplate.getOAuth2ClientContext().setAccessToken(accessToken);

其中,client 是 OAuth2ProtectedResourceDetails 類型的對象,包含 Client ID 和 Client Secret 等資訊。

OAuth2 密碼模式

密碼模式是OAuth2 中適用於信任客戶端的授權類型,它包含以下步驟:

  • Client 向Authorization Server 發送請求,包括Client ID、Client Secret 和Resource Owner 的使用者名稱密碼;
  • Authorization Server 驗證Client ID、Client Secret 和使用者名稱密碼,如果正確,請頒發存取權杖給Client;
  • Client 使用存取權杖向Resource Server 傳送請求。

在 Java API 開發中,可以使用 Spring Security OAuth2 框架實作密碼模式的識別碼。

首先,需要在pom.xml 檔案中新增以下相依性:

<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.3.4.RELEASE</version>
</dependency>

然後,在Spring MVC 的設定檔中新增以下設定:

<security:http pattern="/oauth/token" create-session="stateless"
    authentication-manager-ref="authenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <security:intercept-url pattern="/oauth/token" access="isAuthenticated()" method="POST" />
    <security:anonymous enabled="false" />
    <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <security:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
    <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

<security:http pattern="/api/**" create-session="never"
    entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager"
    xmlns="http://www.springframework.org/schema/security">
    <security:anonymous enabled="false" />
    <security:intercept-url pattern="/api/**" access="ROLE_USER" />
    <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

<bean id="clientAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="spring-boot-oauth2" />
    <property name="typeName" value="Basic" />
</bean>

<bean id="oauthAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="spring-boot-oauth2" />
    <property name="typeName" value="Bearer" />
</bean>

<bean id="oauthAccessDeniedHandler"
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

<bean id="clientCredentialsTokenEndpointFilter"
    class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<bean id="resourceServerFilter"
    class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<bean id="accessDecisionManager"
    class="org.springframework.security.access.vote.UnanimousBased"
    xmlns="http://www.springframework.org/schema/beans">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
            <bean class="org.springframework.security.access.vote.RoleVoter" />
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
        </list>
    </constructor-arg>
</bean>

<security:authentication-manager id="authenticationManager">
    <security:authentication-provider user-service-ref="userDetailsService" />
</security:authentication-manager>

<bean id="userDetailsService"
    class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
    <property name="dataSource" ref="dataSource" />
</bean>

其中,/ oauth/token 是用來取得存取權杖的路徑,/api/** 是需要進行鑑權的路徑。

使用OAuth2RestTemplate 發送請求時,需要先取得存取權杖,程式碼如下:

OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(details, new DefaultOAuth2ClientContext());
restTemplate.getOAuth2ClientContext().setAccessToken(accesstoken);

其中,details 是ResourceOwnerPasswordResourceDetails 類型的對象,包含Client ID、Client Secret、使用者名稱和密碼等資訊。

總結

在 Java API 開發中使用 OAuth2 進行鑑權可以保護 API 資源的安全,並且可以讓使用者更方便地授權第三方應用程式存取他們的伺服器資源。本文介紹了 OAuth2 的授權碼模式和密碼模式,並且提供了使用 Spring Security OAuth2 框架實作鑑權的範例程式碼。希望可以對 Java API 開發者有幫助。

以上是Java API 開發中使用 OAuth2 鑑權的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn