Spring-security-oauth2的版本是2.0。java
以下List-1所示web
List-1spring
package org.springframework.security.oauth2.provider; /** * A service that provides the details about an OAuth2 client. * * @author Ryan Heaton */ public interface ClientDetailsService { /** * Load a client by the client id. This method must not return null. * * @param clientId The client id. * @return The client details (never null). * @throws ClientRegistrationException If the client account is locked, expired, disabled, or invalid for any other reason. */ ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException; }
ClientDetailsService的實現類有InMemoryClientDetailsService和JdbcClientDetailsService。sql
List-2 InMemoryClientDetailsService數據庫
package org.springframework.security.oauth2.provider.client; import java.util.HashMap; import java.util.Map; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.NoSuchClientException; /** * Basic, in-memory implementation of the client details service. * * @author Ryan Heaton */ public class InMemoryClientDetailsService implements ClientDetailsService { private Map<String, ClientDetails> clientDetailsStore = new HashMap<String, ClientDetails>(); public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { ClientDetails details = clientDetailsStore.get(clientId); if (details == null) { throw new NoSuchClientException("No client with requested id: " + clientId); } return details; } public void setClientDetailsStore(Map<String, ? extends ClientDetails> clientDetailsStore) { this.clientDetailsStore = new HashMap<String, ClientDetails>(clientDetailsStore); } }
InMemoryClientDetailsService如List-2所示,將ClientDetails存儲到Hashmap中。json
JdbcClientDetailsService則是將ClientDetails存儲在數據庫中,以下List-3所示app
List-3 JdbcClientDetailsService的loadClientByClientIdide
public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException { ClientDetails details; try { details = jdbcTemplate.queryForObject(selectClientDetailsSql, new ClientDetailsRowMapper(), clientId); } catch (EmptyResultDataAccessException e) { throw new NoSuchClientException("No client with requested id: " + clientId); } return details; }
如List-3,用jdbcTemplate從數據庫中查詢,來看下selectClientDetailsSql,以下List-4this
List-4code
select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?
來看下ClientDetailsRowMapper,以下List-5,最終返回的是BaseClientDetails。
List-5
private static class ClientDetailsRowMapper implements RowMapper<ClientDetails> { private JsonMapper mapper = createJsonMapper(); public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { BaseClientDetails details = new BaseClientDetails(rs.getString(1), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(7), rs.getString(6)); details.setClientSecret(rs.getString(2)); if (rs.getObject(8) != null) { details.setAccessTokenValiditySeconds(rs.getInt(8)); } if (rs.getObject(9) != null) { details.setRefreshTokenValiditySeconds(rs.getInt(9)); } String json = rs.getString(10); if (json != null) { try { @SuppressWarnings("unchecked") Map<String, Object> additionalInformation = mapper.read(json, Map.class); details.setAdditionalInformation(additionalInformation); } catch (Exception e) { logger.warn("Could not decode JSON for additional information: " + details, e); } } String scopes = rs.getString(11); if (scopes != null) { details.setAutoApproveScopes(StringUtils.commaDelimitedListToSet(scopes)); } return details; } }