上一篇文章《实战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输入错误,无法通过这个类来进行错误的判断。
最后按照惯例,附上本案例的源码,登录后即可下载。









还没有评论,来说两句吧...