序言
此次针对 客户端凭证模式 的实践和需求的介绍, 流程的讲解.
需求及场景
在业务系统中需要接收 租户客户的数据信息, 比如 品类信息, 员工信息. 此时我们不可能为每一个客户都进行定义一个接口进行维护其 数据的传输.
思路
我们需要定义出来一个 openApi平台, 提供统一的接入服务, 统一的接口, 为了之后不同的客户传输同一类型的数据做准备.
流程
- 客户需要在平台中进行申请 client信息, 我们进行颁发 client_id 和 client_security . 此时可以进行收费, 例如: 微信公众号自定义服务,需要 300元的开通费用.
- 在进行同步数据的时候, 可以通过 client_id 和 client_security 进行做客户信息的验证以及获取, 为之后的业务逻辑中使用, 例如: 传输的品类, 员工信息是哪个租户的, 为数据隔离做准备.
- post请求接口, https://www.authorization.life/auth-life/oauth2/token
传参:
grant_type: client_credentials – 验证方式.
client_id: passport – 申请时的 client信息
client_secret:3MMoCFo4nTNjRtGZ – 申请的密码明文 - 通过 验证通过之后将返回自定义的 access_token 信息.
配置 OAuth2TokenCustomizer 自定义 token
/**
* 将重写jwtToken的中的信息,并将其存储到redis中。
*
* @param context JwtEncodingContext
*/
@Override
public void customize(JwtEncodingContext context) {
//此处的token字符串是前端拿到的jwtToken信息中解密后的字符串,在这里将自定义jwtToken的实现,将定制jwt的 header 和 claims,将此token存放到 claim 中
String token = UUID.randomUUID().toString(true);
RegisteredClient registeredClient = context.getRegisteredClient();
UserDetail userDetail = null;
// ***** 客户端凭证模式 的判断,匹配 client的Token信息.
if (principal instanceof OAuth2ClientAuthenticationToken) {
//如果当前登录的是client,则进行封装client
userDetail = securityAuthUserService.createUserDetailByClientId(registeredClient.getClientId());
}
//如果解析失败,则抛出异常信息。
if (Objects.isNull(userDetail)) {
log.error("在自定义token实现中, 用户信息解析异常。");
userDetail = new UserDetail();
}
//也需要将此token存放到当前登录用户中,为了在退出登录时进行获取redis中的信息并将其删除
userDetail.setToken(token);
//将用户信息放置到redis中,并设置其过期时间为 client中的过期时间
strRedisHelper.strSet(LifeSecurityConstants.getUserTokenKey(token), userDetail,
registeredClient.getTokenSettings().getAccessTokenTimeToLive().getSeconds(), TimeUnit.SECONDS);
log.info("生成的用户-token是-{},此token作为key,用户信息作为value存储到redis中", token);
//也可以在此处将当前登录用户的信息存放到jwt中,但是这样就不再安全。
context.getClaims().claim(LifeSecurityConstants.TOKEN, token).build();
}