上一篇文章《实战Spring Cloud Oauth2系列(三)自定义查询用户的数据结构》我们介绍了自定义查询用户,在oauth里面,还有一个比较重要的信息就是oauth的客户端应用,每一个应用我们一般都会分配appkey和appsecret,所以这里的话,我们可能也会涉及到数据结构不一样,因此这里也需要来实现自定义的一个查询组装。
还记得在oauth config里面,有一个这个方法:
public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientService); }
在这里,我们是需要设置自定义的客户端查询逻辑的。如果要自定义client的查询逻辑,那么必须要集成ClientDetailsService这个类,示例如下:
package org.shop.oauth.server.service; import org.springframework.security.oauth2.provider.ClientDetailsService; public interface ClientService extends ClientDetailsService { }
在实现查询的时候,我们需要实现这个方法:
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { QueryWrapper<ClientEntity> queryWrapper = new QueryWrapper<ClientEntity>(); queryWrapper.eq("client_id", clientId); // 这里去数据库查询对应的client ClientEntity clientEntity = clientEntityDao.selectOne(queryWrapper); log.info("根据client-id查询到的信息是:{}",JSON.toJSONString(clientEntity)); if (null == clientEntity) { throw new ShopException(ResultCode.NOTFOUNDCLIENT.getMessage()); } return new ClientPrincipal(clientEntity); }
这里也是一样,只有一个通过clientid来查询对应客户端应用的方法,我们可以在里面做一些简单的判断逻辑。最后返回的实体类必须实现ClientDetails这个接口,用以填充oauth自身的client判断。示例如下:
package org.shop.common.mysql.auth.model; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.provider.ClientDetails; import lombok.Data; @Data public class ClientPrincipal implements ClientDetails { /** * */ private static final long serialVersionUID = -2627750900959616931L; private ClientEntity client; public ClientPrincipal(ClientEntity client) { this.client = client; } @Override public String getClientId() { return client.getClient_id(); } @Override public Set<String> getResourceIds() { return new HashSet<>(Arrays.asList(client.getResource_ids().split(","))); } @Override public boolean isSecretRequired() { return false; } @Override public String getClientSecret() { return client.getClient_secret(); } @Override public boolean isScoped() { return false; } @Override public Set<String> getScope() { return new HashSet<>(Arrays.asList(client.getScope().split(","))); } @Override public Set<String> getAuthorizedGrantTypes() { return new HashSet<>(Arrays.asList(client.getAuthorized_grant_types().split(","))); } @Override public Set<String> getRegisteredRedirectUri() { return new HashSet<>(Arrays.asList(client.getWeb_server_redirect_uri().split(","))); } @Override public Collection<GrantedAuthority> getAuthorities() { Collection<GrantedAuthority> collection = new ArrayList<>(); Arrays.asList(client.getAuthorities().split(",")) .forEach(auth -> collection.add((GrantedAuthority) () -> auth)); return collection; } @Override public Integer getAccessTokenValiditySeconds() { return client.getAccess_token_validity(); } @Override public Integer getRefreshTokenValiditySeconds() { return client.getRefresh_token_validity(); } @Override public boolean isAutoApprove(String s) { return false; } @Override public Map<String, Object> getAdditionalInformation() { return null; } }
以上就是实现自定义客户端查询的案例,
备注:
1、这里和user是一样的,如果secret输入错误,无法通过这个类来进行错误的判断。
最后按照惯例,附上本案例的源码,登录后即可下载。
还没有评论,来说两句吧...