全球今亮點!如何使用JPA實現Spring 授權服務器的核心服務

2022-12-06 17:46:50 來源:51CTO博客

本指南展示了如何使用JPA實現Spring 授權服務器?的核心服務。 本指南的目的是提供自己實現這些服務的起點,以便您可以根據需要進行修改。

定義數據模型創建 JPA 實體創建 Spring 數據存儲庫實施核心服務

定義數據模型

本指南提供了數據模型的起點,并使用了最簡單的結構和數據類型。 為了提出初始架構,我們首先查看核心服務使用的域對象。

除了令牌、狀態、元數據、設置和聲明值之外,我們對所有列使用 JPA 默認列長度 255。 實際上,您可能需要自定義您使用的列的長度甚至類型。 建議你在部署到生產環境之前進行試驗和測試。


(資料圖)

客戶端架構授權架構授權同意架構

客戶端架構

RegisterClient域對象包含一些多值字段和一些需要存儲任意鍵/值數據的設置字段。 以下清單顯示了架構。??client??

客戶端架構

CREATE TABLE client (    id varchar(255) NOT NULL,    clientId varchar(255) NOT NULL,    clientIdIssuedAt timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,    clientSecret varchar(255) DEFAULT NULL,    clientSecretExpiresAt timestamp DEFAULT NULL,    clientName varchar(255) NOT NULL,    clientAuthenticationMethods varchar(1000) NOT NULL,    authorizationGrantTypes varchar(1000) NOT NULL,    redirectUris varchar(1000) DEFAULT NULL,    scopes varchar(1000) NOT NULL,    clientSettings varchar(2000) NOT NULL,    tokenSettings varchar(2000) NOT NULL,    PRIMARY KEY (id));

授權架構

OAuth2Authorization域對象更為復雜,包含多個多值字段以及大量任意長的令牌值、元數據、設置和聲明值。 內置的 JDBC 實現利用扁平化結構,該結構更喜歡性能而不是規范化,我們在這里也采用這種結構。

很難找到一種在所有情況下和所有數據庫供應商都能正常工作的扁平數據庫模式。 您可能需要根據需要規范化或大量更改以下架構。

以下清單顯示了架構。??authorization??

授權架構

CREATE TABLE authorization (    id varchar(255) NOT NULL,    registeredClientId varchar(255) NOT NULL,    principalName varchar(255) NOT NULL,    authorizationGrantType varchar(255) NOT NULL,    attributes varchar(4000) DEFAULT NULL,    state varchar(500) DEFAULT NULL,    authorizationCodeValue varchar(4000) DEFAULT NULL,    authorizationCodeIssuedAt timestamp DEFAULT NULL,    authorizationCodeExpiresAt timestamp DEFAULT NULL,    authorizationCodeMetadata varchar(2000) DEFAULT NULL,    accessTokenValue varchar(4000) DEFAULT NULL,    accessTokenIssuedAt timestamp DEFAULT NULL,    accessTokenExpiresAt timestamp DEFAULT NULL,    accessTokenMetadata varchar(2000) DEFAULT NULL,    accessTokenType varchar(255) DEFAULT NULL,    accessTokenScopes varchar(1000) DEFAULT NULL,    refreshTokenValue varchar(4000) DEFAULT NULL,    refreshTokenIssuedAt timestamp DEFAULT NULL,    refreshTokenExpiresAt timestamp DEFAULT NULL,    refreshTokenMetadata varchar(2000) DEFAULT NULL,    oidcIdTokenValue varchar(4000) DEFAULT NULL,    oidcIdTokenIssuedAt timestamp DEFAULT NULL,    oidcIdTokenExpiresAt timestamp DEFAULT NULL,    oidcIdTokenMetadata varchar(2000) DEFAULT NULL,    oidcIdTokenClaims varchar(2000) DEFAULT NULL,    PRIMARY KEY (id));

授權同意架構

OAuth2AuthorizationConsent域對象是最容易建模的,除了組合鍵外,還只包含一個多值字段。 以下清單顯示了架構。??authorizationConsent??

授權同意架構

CREATE TABLE authorizationConsent (    registeredClientId varchar(255) NOT NULL,    principalName varchar(255) NOT NULL,    authorities varchar(1000) NOT NULL,    PRIMARY KEY (registeredClientId, principalName));

創建 JPA 實體

前面的架構示例為我們需要創建的實體的結構提供了參考。

以下實體是最少注釋的,只是示例。 它們允許動態創建架構,因此不需要手動執行上述 sql 腳本。

客戶實體授權實體授權同意實體

客戶實體

下面的清單顯示了實體,該實體用于保存從Registered Client域對象映射的信息。??Client??

客戶實體

@Entity@Table(name = "`client`")public class Client {  @Id  private String id;  private String clientId;  private Instant clientIdIssuedAt;  private String clientSecret;  private Instant clientSecretExpiresAt;  private String clientName;  @Column(length = 1000)  private String clientAuthenticationMethods;  @Column(length = 1000)  private String authorizationGrantTypes;  @Column(length = 1000)  private String redirectUris;  @Column(length = 1000)  private String scopes;  @Column(length = 2000)  private String clientSettings;  @Column(length = 2000)  private String tokenSettings;}

授權實體

下面的清單顯示了實體,該實體用于保存從OAuth2Authorization域對象映射的信息。??Authorization??

授權實體

@Entity@Table(name = "`authorization`")public class Authorization {  @Id  @Column  private String id;  private String registeredClientId;  private String principalName;  private String authorizationGrantType;  @Column(length = 1000)  private String authorizedScopes;  @Column(length = 4000)  private String attributes;  @Column(length = 500)  private String state;  @Column(length = 4000)  private String authorizationCodeValue;  private Instant authorizationCodeIssuedAt;  private Instant authorizationCodeExpiresAt;  private String authorizationCodeMetadata;  @Column(length = 4000)  private String accessTokenValue;  private Instant accessTokenIssuedAt;  private Instant accessTokenExpiresAt;  @Column(length = 2000)  private String accessTokenMetadata;  private String accessTokenType;  @Column(length = 1000)  private String accessTokenScopes;  @Column(length = 4000)  private String refreshTokenValue;  private Instant refreshTokenIssuedAt;  private Instant refreshTokenExpiresAt;  @Column(length = 2000)  private String refreshTokenMetadata;  @Column(length = 4000)  private String oidcIdTokenValue;  private Instant oidcIdTokenIssuedAt;  private Instant oidcIdTokenExpiresAt;  @Column(length = 2000)  private String oidcIdTokenMetadata;  @Column(length = 2000)  private String oidcIdTokenClaims;}

授權同意實體

下面的清單顯示了實體,該實體用于保存從OAuth2AuthorizationConsent域對象映射的信息。??AuthorizationConsent??

授權同意實體

@Entity@Table(name = "`authorizationConsent`")@IdClass(AuthorizationConsent.AuthorizationConsentId.class)public class AuthorizationConsent {  @Id  private String registeredClientId;  @Id  private String principalName;  @Column(length = 1000)  private String authorities;  public static class AuthorizationConsentId implements Serializable {    private String registeredClientId;    private String principalName;    @Override    public boolean equals(Object o) {      if (this == o) return true;      if (o == null || getClass() != o.getClass()) return false;      AuthorizationConsentId that = (AuthorizationConsentId) o;      return registeredClientId.equals(that.registeredClientId) && principalName.equals(that.principalName);    }    @Override    public int hashCode() {      return Objects.hash(registeredClientId, principalName);    }  }}

創建 Spring 數據存儲庫

通過仔細檢查每個核心服務的接口并查看實現,我們可以派生出支持每個接口的 JPA 版本所需的最少查詢集。??Jdbc??

客戶端存儲庫授權存儲庫授權同意存儲庫

客戶端存儲庫

下面的清單顯示了,它能夠通過 andfields 找到客戶端。??ClientRepository????id????clientId??

客戶端存儲庫

@Repositorypublic interface ClientRepository extends JpaRepository {  Optional findByClientId(String clientId);}

授權存儲庫

下面的清單顯示了 ,它能夠找到授權字段以及,,和令牌字段。 它還允許查詢令牌字段的組合。??AuthorizationRepository????id????state????authorizationCodeValue????accessTokenValue????refreshTokenValue??

授權存儲庫

@Repositorypublic interface AuthorizationRepository extends JpaRepository {  Optional findByState(String state);  Optional findByAuthorizationCodeValue(String authorizationCode);  Optional findByAccessTokenValue(String accessToken);  Optional findByRefreshTokenValue(String refreshToken);  @Query("select a from Authorization a where a.state = :token" +      " or a.authorizationCodeValue = :token" +      " or a.accessTokenValue = :token" +      " or a.refreshTokenValue = :token"  )  Optional findByStateOrAuthorizationCodeValueOrAccessTokenValueOrRefreshTokenValue(@Param("token") String token);}

授權同意存儲庫

下面的清單顯示了 ,它能夠通過形成復合主鍵的 andfields 查找和刪除授權同意。??AuthorizationConsentRepository????registeredClientId????principalName??

授權同意存儲庫

@Repositorypublic interface AuthorizationConsentRepository extends JpaRepository {  Optional findByRegisteredClientIdAndPrincipalName(String registeredClientId, String principalName);  void deleteByRegisteredClientIdAndPrincipalName(String registeredClientId, String principalName);}

實施核心服務

有了上述實體和存儲庫,我們可以開始實施核心服務。 通過查看實現,我們可以派生一組最小的內部實用程序,用于在枚舉的字符串值之間轉換,以及讀取和寫入屬性、設置、元數據和聲明字段的 JSON 數據。??Jdbc??

請記住,將 JSON 數據寫入具有固定長度的文本列已被證明在實現中存在問題。 雖然這些示例繼續這樣做,但您可能需要將這些字段拆分為支持任意長數據值的單獨表或數據存儲。??Jdbc??

已注冊的客戶端存儲庫授權服務授權同意服務

已注冊的客戶端存儲庫

下面的清單顯示了 ,它使用ClientRepository來持久化客戶端,并映射到 RegisterClient 域對象和從Registered Client域對象映射。??JpaRegisteredClientRepository??

??RegisteredClientRepository??實現

@Componentpublic class JpaRegisteredClientRepository implements RegisteredClientRepository {  private final ClientRepository clientRepository;  private final ObjectMapper objectMapper = new ObjectMapper();  public JpaRegisteredClientRepository(ClientRepository clientRepository) {    Assert.notNull(clientRepository, "clientRepository cannot be null");    this.clientRepository = clientRepository;    ClassLoader classLoader = JpaRegisteredClientRepository.class.getClassLoader();    List securityModules = SecurityJackson2Modules.getModules(classLoader);    this.objectMapper.registerModules(securityModules);    this.objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());  }  @Override  public void save(RegisteredClient registeredClient) {    Assert.notNull(registeredClient, "registeredClient cannot be null");    this.clientRepository.save(toEntity(registeredClient));  }  @Override  public RegisteredClient findById(String id) {    Assert.hasText(id, "id cannot be empty");    return this.clientRepository.findById(id).map(this::toObject).orElse(null);  }  @Override  public RegisteredClient findByClientId(String clientId) {    Assert.hasText(clientId, "clientId cannot be empty");    return this.clientRepository.findByClientId(clientId).map(this::toObject).orElse(null);  }  private RegisteredClient toObject(Client client) {    Set clientAuthenticationMethods = StringUtils.commaDelimitedListToSet(        client.getClientAuthenticationMethods());    Set authorizationGrantTypes = StringUtils.commaDelimitedListToSet(        client.getAuthorizationGrantTypes());    Set redirectUris = StringUtils.commaDelimitedListToSet(        client.getRedirectUris());    Set clientScopes = StringUtils.commaDelimitedListToSet(        client.getScopes());    RegisteredClient.Builder builder = RegisteredClient.withId(client.getId())        .clientId(client.getClientId())        .clientIdIssuedAt(client.getClientIdIssuedAt())        .clientSecret(client.getClientSecret())        .clientSecretExpiresAt(client.getClientSecretExpiresAt())        .clientName(client.getClientName())        .clientAuthenticationMethods(authenticationMethods ->            clientAuthenticationMethods.forEach(authenticationMethod ->                authenticationMethods.add(resolveClientAuthenticationMethod(authenticationMethod))))        .authorizationGrantTypes((grantTypes) ->            authorizationGrantTypes.forEach(grantType ->                grantTypes.add(resolveAuthorizationGrantType(grantType))))        .redirectUris((uris) -> uris.addAll(redirectUris))        .scopes((scopes) -> scopes.addAll(clientScopes));    Map clientSettingsMap = parseMap(client.getClientSettings());    builder.clientSettings(ClientSettings.withSettings(clientSettingsMap).build());    Map tokenSettingsMap = parseMap(client.getTokenSettings());    builder.tokenSettings(TokenSettings.withSettings(tokenSettingsMap).build());    return builder.build();  }  private Client toEntity(RegisteredClient registeredClient) {    List clientAuthenticationMethods = new ArrayList<>(registeredClient.getClientAuthenticationMethods().size());    registeredClient.getClientAuthenticationMethods().forEach(clientAuthenticationMethod ->        clientAuthenticationMethods.add(clientAuthenticationMethod.getValue()));    List authorizationGrantTypes = new ArrayList<>(registeredClient.getAuthorizationGrantTypes().size());    registeredClient.getAuthorizationGrantTypes().forEach(authorizationGrantType ->        authorizationGrantTypes.add(authorizationGrantType.getValue()));    Client entity = new Client();    entity.setId(registeredClient.getId());    entity.setClientId(registeredClient.getClientId());    entity.setClientIdIssuedAt(registeredClient.getClientIdIssuedAt());    entity.setClientSecret(registeredClient.getClientSecret());    entity.setClientSecretExpiresAt(registeredClient.getClientSecretExpiresAt());    entity.setClientName(registeredClient.getClientName());    entity.setClientAuthenticationMethods(StringUtils.collectionToCommaDelimitedString(clientAuthenticationMethods));    entity.setAuthorizationGrantTypes(StringUtils.collectionToCommaDelimitedString(authorizationGrantTypes));    entity.setRedirectUris(StringUtils.collectionToCommaDelimitedString(registeredClient.getRedirectUris()));    entity.setScopes(StringUtils.collectionToCommaDelimitedString(registeredClient.getScopes()));    entity.setClientSettings(writeMap(registeredClient.getClientSettings().getSettings()));    entity.setTokenSettings(writeMap(registeredClient.getTokenSettings().getSettings()));    return entity;  }  private Map parseMap(String data) {    try {      return this.objectMapper.readValue(data, new TypeReference>() {      });    } catch (Exception ex) {      throw new IllegalArgumentException(ex.getMessage(), ex);    }  }  private String writeMap(Map data) {    try {      return this.objectMapper.writeValueAsString(data);    } catch (Exception ex) {      throw new IllegalArgumentException(ex.getMessage(), ex);    }  }  private static AuthorizationGrantType resolveAuthorizationGrantType(String authorizationGrantType) {    if (AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals(authorizationGrantType)) {      return AuthorizationGrantType.AUTHORIZATION_CODE;    } else if (AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equals(authorizationGrantType)) {      return AuthorizationGrantType.CLIENT_CREDENTIALS;    } else if (AuthorizationGrantType.REFRESH_TOKEN.getValue().equals(authorizationGrantType)) {      return AuthorizationGrantType.REFRESH_TOKEN;    }    return new AuthorizationGrantType(authorizationGrantType);              // Custom authorization grant type  }  private static ClientAuthenticationMethod resolveClientAuthenticationMethod(String clientAuthenticationMethod) {    if (ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue().equals(clientAuthenticationMethod)) {      return ClientAuthenticationMethod.CLIENT_SECRET_BASIC;    } else if (ClientAuthenticationMethod.CLIENT_SECRET_POST.getValue().equals(clientAuthenticationMethod)) {      return ClientAuthenticationMethod.CLIENT_SECRET_POST;    } else if (ClientAuthenticationMethod.NONE.getValue().equals(clientAuthenticationMethod)) {      return ClientAuthenticationMethod.NONE;    }    return new ClientAuthenticationMethod(clientAuthenticationMethod);      // Custom client authentication method  }}

授權服務

下面的清單顯示了 ,它使用AuthorizationRepository來持久保存授權,并映射到 OAuth2Authorization 域對象和從OAuth2Authorization域對象映射。??JpaOAuth2AuthorizationService??

??OAuth2AuthorizationService??實現

@Componentpublic class JpaOAuth2AuthorizationService implements OAuth2AuthorizationService {  private final AuthorizationRepository authorizationRepository;  private final RegisteredClientRepository registeredClientRepository;  private final ObjectMapper objectMapper = new ObjectMapper();  public JpaOAuth2AuthorizationService(AuthorizationRepository authorizationRepository, RegisteredClientRepository registeredClientRepository) {    Assert.notNull(authorizationRepository, "authorizationRepository cannot be null");    Assert.notNull(registeredClientRepository, "registeredClientRepository cannot be null");    this.authorizationRepository = authorizationRepository;    this.registeredClientRepository = registeredClientRepository;    ClassLoader classLoader = JpaOAuth2AuthorizationService.class.getClassLoader();    List securityModules = SecurityJackson2Modules.getModules(classLoader);    this.objectMapper.registerModules(securityModules);    this.objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());  }  @Override  public void save(OAuth2Authorization authorization) {    Assert.notNull(authorization, "authorization cannot be null");    this.authorizationRepository.save(toEntity(authorization));  }  @Override  public void remove(OAuth2Authorization authorization) {    Assert.notNull(authorization, "authorization cannot be null");    this.authorizationRepository.deleteById(authorization.getId());  }  @Override  public OAuth2Authorization findById(String id) {    Assert.hasText(id, "id cannot be empty");    return this.authorizationRepository.findById(id).map(this::toObject).orElse(null);  }  @Override  public OAuth2Authorization findByToken(String token, OAuth2TokenType tokenType) {    Assert.hasText(token, "token cannot be empty");    Optional result;    if (tokenType == null) {      result = this.authorizationRepository.findByStateOrAuthorizationCodeValueOrAccessTokenValueOrRefreshTokenValue(token);    } else if (OAuth2ParameterNames.STATE.equals(tokenType.getValue())) {      result = this.authorizationRepository.findByState(token);    } else if (OAuth2ParameterNames.CODE.equals(tokenType.getValue())) {      result = this.authorizationRepository.findByAuthorizationCodeValue(token);    } else if (OAuth2ParameterNames.ACCESS_TOKEN.equals(tokenType.getValue())) {      result = this.authorizationRepository.findByAccessTokenValue(token);    } else if (OAuth2ParameterNames.REFRESH_TOKEN.equals(tokenType.getValue())) {      result = this.authorizationRepository.findByRefreshTokenValue(token);    } else {      result = Optional.empty();    }    return result.map(this::toObject).orElse(null);  }  private OAuth2Authorization toObject(Authorization entity) {    RegisteredClient registeredClient = this.registeredClientRepository.findById(entity.getRegisteredClientId());    if (registeredClient == null) {      throw new DataRetrievalFailureException(          "The RegisteredClient with id "" + entity.getRegisteredClientId() + "" was not found in the RegisteredClientRepository.");    }    OAuth2Authorization.Builder builder = OAuth2Authorization.withRegisteredClient(registeredClient)        .id(entity.getId())        .principalName(entity.getPrincipalName())        .authorizationGrantType(resolveAuthorizationGrantType(entity.getAuthorizationGrantType()))        .authorizedScopes(StringUtils.commaDelimitedListToSet(entity.getAuthorizedScopes()))        .attributes(attributes -> attributes.putAll(parseMap(entity.getAttributes())));    if (entity.getState() != null) {      builder.attribute(OAuth2ParameterNames.STATE, entity.getState());    }    if (entity.getAuthorizationCodeValue() != null) {      OAuth2AuthorizationCode authorizationCode = new OAuth2AuthorizationCode(          entity.getAuthorizationCodeValue(),          entity.getAuthorizationCodeIssuedAt(),          entity.getAuthorizationCodeExpiresAt());      builder.token(authorizationCode, metadata -> metadata.putAll(parseMap(entity.getAuthorizationCodeMetadata())));    }    if (entity.getAccessTokenValue() != null) {      OAuth2AccessToken accessToken = new OAuth2AccessToken(          OAuth2AccessToken.TokenType.BEARER,          entity.getAccessTokenValue(),          entity.getAccessTokenIssuedAt(),          entity.getAccessTokenExpiresAt(),          StringUtils.commaDelimitedListToSet(entity.getAccessTokenScopes()));      builder.token(accessToken, metadata -> metadata.putAll(parseMap(entity.getAccessTokenMetadata())));    }    if (entity.getRefreshTokenValue() != null) {      OAuth2RefreshToken refreshToken = new OAuth2RefreshToken(          entity.getRefreshTokenValue(),          entity.getRefreshTokenIssuedAt(),          entity.getRefreshTokenExpiresAt());      builder.token(refreshToken, metadata -> metadata.putAll(parseMap(entity.getRefreshTokenMetadata())));    }    if (entity.getOidcIdTokenValue() != null) {      OidcIdToken idToken = new OidcIdToken(          entity.getOidcIdTokenValue(),          entity.getOidcIdTokenIssuedAt(),          entity.getOidcIdTokenExpiresAt(),          parseMap(entity.getOidcIdTokenClaims()));      builder.token(idToken, metadata -> metadata.putAll(parseMap(entity.getOidcIdTokenMetadata())));    }    return builder.build();  }  private Authorization toEntity(OAuth2Authorization authorization) {    Authorization entity = new Authorization();    entity.setId(authorization.getId());    entity.setRegisteredClientId(authorization.getRegisteredClientId());    entity.setPrincipalName(authorization.getPrincipalName());    entity.setAuthorizationGrantType(authorization.getAuthorizationGrantType().getValue());    entity.setAuthorizedScopes(StringUtils.collectionToDelimitedString(authorization.getAuthorizedScopes(), ","));    entity.setAttributes(writeMap(authorization.getAttributes()));    entity.setState(authorization.getAttribute(OAuth2ParameterNames.STATE));    OAuth2Authorization.Token authorizationCode =        authorization.getToken(OAuth2AuthorizationCode.class);    setTokenValues(        authorizationCode,        entity::setAuthorizationCodeValue,        entity::setAuthorizationCodeIssuedAt,        entity::setAuthorizationCodeExpiresAt,        entity::setAuthorizationCodeMetadata    );    OAuth2Authorization.Token accessToken =        authorization.getToken(OAuth2AccessToken.class);    setTokenValues(        accessToken,        entity::setAccessTokenValue,        entity::setAccessTokenIssuedAt,        entity::setAccessTokenExpiresAt,        entity::setAccessTokenMetadata    );    if (accessToken != null && accessToken.getToken().getScopes() != null) {      entity.setAccessTokenScopes(StringUtils.collectionToDelimitedString(accessToken.getToken().getScopes(), ","));    }    OAuth2Authorization.Token refreshToken =        authorization.getToken(OAuth2RefreshToken.class);    setTokenValues(        refreshToken,        entity::setRefreshTokenValue,        entity::setRefreshTokenIssuedAt,        entity::setRefreshTokenExpiresAt,        entity::setRefreshTokenMetadata    );    OAuth2Authorization.Token oidcIdToken =        authorization.getToken(OidcIdToken.class);    setTokenValues(        oidcIdToken,        entity::setOidcIdTokenValue,        entity::setOidcIdTokenIssuedAt,        entity::setOidcIdTokenExpiresAt,        entity::setOidcIdTokenMetadata    );    if (oidcIdToken != null) {      entity.setOidcIdTokenClaims(writeMap(oidcIdToken.getClaims()));    }    return entity;  }  private void setTokenValues(      OAuth2Authorization.Token token,      Consumer tokenValueConsumer,      Consumer issuedAtConsumer,      Consumer expiresAtConsumer,      Consumer metadataConsumer) {    if (token != null) {      OAuth2Token oAuth2Token = token.getToken();      tokenValueConsumer.accept(oAuth2Token.getTokenValue());      issuedAtConsumer.accept(oAuth2Token.getIssuedAt());      expiresAtConsumer.accept(oAuth2Token.getExpiresAt());      metadataConsumer.accept(writeMap(token.getMetadata()));    }  }  private Map parseMap(String data) {    try {      return this.objectMapper.readValue(data, new TypeReference>() {      });    } catch (Exception ex) {      throw new IllegalArgumentException(ex.getMessage(), ex);    }  }  private String writeMap(Map metadata) {    try {      return this.objectMapper.writeValueAsString(metadata);    } catch (Exception ex) {      throw new IllegalArgumentException(ex.getMessage(), ex);    }  }  private static AuthorizationGrantType resolveAuthorizationGrantType(String authorizationGrantType) {    if (AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals(authorizationGrantType)) {      return AuthorizationGrantType.AUTHORIZATION_CODE;    } else if (AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equals(authorizationGrantType)) {      return AuthorizationGrantType.CLIENT_CREDENTIALS;    } else if (AuthorizationGrantType.REFRESH_TOKEN.getValue().equals(authorizationGrantType)) {      return AuthorizationGrantType.REFRESH_TOKEN;    }    return new AuthorizationGrantType(authorizationGrantType);              // Custom authorization grant type  }}

授權同意服務

下面的清單顯示了 ,它使用AuthorizationConsentRepository來持久保存 AuthorizationConsent,并映射到 OAuth2AuthorizationConsent 域對象和從OAuth2AuthorizationConsent域對象映射。??JpaOAuth2AuthorizationConsentService??

??OAuth2AuthorizationConsentService??實現

@Componentpublic class JpaOAuth2AuthorizationConsentService implements OAuth2AuthorizationConsentService {  private final AuthorizationConsentRepository authorizationConsentRepository;  private final RegisteredClientRepository registeredClientRepository;  public JpaOAuth2AuthorizationConsentService(AuthorizationConsentRepository authorizationConsentRepository, RegisteredClientRepository registeredClientRepository) {    Assert.notNull(authorizationConsentRepository, "authorizationConsentRepository cannot be null");    Assert.notNull(registeredClientRepository, "registeredClientRepository cannot be null");    this.authorizationConsentRepository = authorizationConsentRepository;    this.registeredClientRepository = registeredClientRepository;  }  @Override  public void save(OAuth2AuthorizationConsent authorizationConsent) {    Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");    this.authorizationConsentRepository.save(toEntity(authorizationConsent));  }  @Override  public void remove(OAuth2AuthorizationConsent authorizationConsent) {    Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");    this.authorizationConsentRepository.deleteByRegisteredClientIdAndPrincipalName(        authorizationConsent.getRegisteredClientId(), authorizationConsent.getPrincipalName());  }  @Override  public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) {    Assert.hasText(registeredClientId, "registeredClientId cannot be empty");    Assert.hasText(principalName, "principalName cannot be empty");    return this.authorizationConsentRepository.findByRegisteredClientIdAndPrincipalName(        registeredClientId, principalName).map(this::toObject).orElse(null);  }  private OAuth2AuthorizationConsent toObject(AuthorizationConsent authorizationConsent) {    String registeredClientId = authorizationConsent.getRegisteredClientId();    RegisteredClient registeredClient = this.registeredClientRepository.findById(registeredClientId);    if (registeredClient == null) {      throw new DataRetrievalFailureException(          "The RegisteredClient with id "" + registeredClientId + "" was not found in the RegisteredClientRepository.");    }    OAuth2AuthorizationConsent.Builder builder = OAuth2AuthorizationConsent.withId(        registeredClientId, authorizationConsent.getPrincipalName());    if (authorizationConsent.getAuthorities() != null) {      for (String authority : StringUtils.commaDelimitedListToSet(authorizationConsent.getAuthorities())) {        builder.authority(new SimpleGrantedAuthority(authority));      }    }    return builder.build();  }  private AuthorizationConsent toEntity(OAuth2AuthorizationConsent authorizationConsent) {    AuthorizationConsent entity = new AuthorizationConsent();    entity.setRegisteredClientId(authorizationConsent.getRegisteredClientId());    entity.setPrincipalName(authorizationConsent.getPrincipalName());    Set authorities = new HashSet<>();    for (GrantedAuthority authority : authorizationConsent.getAuthorities()) {      authorities.add(authority.getAuthority());    }    entity.setAuthorities(StringUtils.collectionToCommaDelimitedString(authorities));    return entity;  }}

標簽: 數據存儲 數據模型 根據需要

上一篇:魯甘“工匠聯盟”:技工院校“結對幫扶”育人才
下一篇:環球微資訊!Spring Session for Apache Geode 教程