新增 SaOAuth2DataResolver 数据解析器,负责 Web 交互层面的数据进出

This commit is contained in:
click33
2024-08-13 15:04:39 +08:00
parent b1e2e8a526
commit ae87b11d43
13 changed files with 270 additions and 57 deletions

View File

@@ -16,8 +16,10 @@
package cn.dev33.satoken.oauth2;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.dataloader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.dataloader.SaOAuth2DataLoaderDefaultImpl;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoaderDefaultImpl;
import cn.dev33.satoken.oauth2.data.resolver.SaOAuth2DataResolver;
import cn.dev33.satoken.oauth2.data.resolver.SaOAuth2DataResolverDefaultImpl;
/**
* Sa-Token-OAuth2 模块 总控类
@@ -64,4 +66,22 @@ public class SaOAuth2Manager {
SaOAuth2Manager.dataLoader = dataLoader;
}
/**
* OAuth2 数据解析器 Bean
*/
private static volatile SaOAuth2DataResolver dataResolver;
public static SaOAuth2DataResolver getDataResolver() {
if (dataResolver == null) {
synchronized (SaOAuth2Manager.class) {
if (dataResolver == null) {
setDataResolver(new SaOAuth2DataResolverDefaultImpl());
}
}
}
return dataResolver;
}
public static void setDataResolver(SaOAuth2DataResolver dataResolver) {
SaOAuth2Manager.dataResolver = dataResolver;
}
}

View File

@@ -77,7 +77,22 @@ public class SaOAuth2Consts {
public static String client_credentials = "client_credentials";
public static String implicit = "implicit";
}
/**
* 所有 token 类型
*/
public static final class TokenType {
// 全小写
public static String basic = "basic";
public static String digest = "digest";
public static String bearer = "bearer";
// 首字母大写
public static String Basic = "Basic";
public static String Digest = "Digest";
public static String Bearer = "Bearer";
}
/** 表示OK的返回结果 */
public static final String OK = "ok";

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.dataloader;
package cn.dev33.satoken.oauth2.data.loader;
import cn.dev33.satoken.oauth2.model.SaClientModel;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.dataloader;
package cn.dev33.satoken.oauth2.data.loader;
/**
* Sa-Token OAuth2 数据加载器 默认实现类

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.data.resolver;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.ClientTokenModel;
import cn.dev33.satoken.util.SaResult;
import java.util.Map;
/**
* Sa-Token OAuth2 数据解析器,负责 Web 交互层面的数据进出:
* <p>1、从请求中按照指定格式读取数据</p>
* <p>2、构建数据输出格式</p>
*
* @author click33
* @since 1.39.0
*/
public interface SaOAuth2DataResolver {
/**
* 构建返回值: 获取 token
* @param at token信息
* @return /
*/
Map<String, Object> buildTokenReturnValue(AccessTokenModel at);
/**
* 构建返回值: RefreshToken 刷新 Access-Token
* @param at token信息
* @return /
*/
default Map<String, Object> buildRefreshTokenReturnValue(AccessTokenModel at) {
return buildTokenReturnValue(at);
}
/**
* 构建返回值: 回收 Access-Token
* @return /
*/
default Map<String, Object> buildRevokeTokenReturnValue() {
return SaResult.ok();
}
/**
* 构建返回值: password 模式认证 获取 token
* @param at token信息
* @return /
*/
default Map<String, Object> buildPasswordReturnValue(AccessTokenModel at) {
return buildTokenReturnValue(at);
}
/**
* 构建返回值: 凭证式 模式认证 获取 token
* @param ct token信息
*/
Map<String, Object> buildClientTokenReturnValue(ClientTokenModel ct);
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.data.resolver;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.TokenType;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.ClientTokenModel;
import cn.dev33.satoken.util.SaResult;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Sa-Token OAuth2 数据解析器,负责 Web 交互层面的数据进出:
* <p>1、从请求中按照指定格式读取数据</p>
* <p>2、构建数据输出格式</p>
*
* @author click33
* @since 1.39.0
*/
public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
/**
* 构建返回值: 获取 token
*/
public Map<String, Object> buildTokenReturnValue(AccessTokenModel at) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("token_type", TokenType.bearer);
map.put("access_token", at.accessToken);
map.put("refresh_token", at.refreshToken);
map.put("expires_in", at.getExpiresIn());
map.put("refresh_expires_in", at.getRefreshExpiresIn());
map.put("client_id", at.clientId);
map.put("scope", at.scope);
map.put("openid", at.openid);
return SaResult.ok().setMap(map);
}
/**
* 构建返回值: password 模式认证 获取 token
*/
@Override
public Map<String, Object> buildClientTokenReturnValue(ClientTokenModel ct) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("client_token", ct.clientToken);
map.put("access_token", ct.clientToken); // 兼容 OAuth2 协议
map.put("expires_in", ct.getExpiresIn());
map.put("client_id", ct.clientId);
map.put("scope", ct.scope);
return SaResult.ok().setMap(map);
}
}

View File

@@ -61,7 +61,6 @@ public class SaOAuth2ServerProcessor {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// ------------------ 路由分发 ------------------
@@ -187,14 +186,13 @@ public class SaOAuth2ServerProcessor {
public Object token() {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// 获取参数
String authorizationValue = SaHttpBasicUtil.getAuthorizationValue();
String clientId;
String clientSecret;
// gitlab回调token接口时,按照的是标准的oauth2协议的basic请求头,basic中会包含client_id和client_secret的信息
// gitlab 回调 token 接口时,按照的是标准的oauth2协议的basic请求头,basic中会包含client_id和client_secret的信息
if(SaFoxUtil.isEmpty(authorizationValue)){
clientId = req.getParamNotNull(Param.client_id);
clientSecret = req.getParamNotNull(Param.client_secret);
@@ -211,10 +209,10 @@ public class SaOAuth2ServerProcessor {
oauth2Template.checkGainTokenParam(code, clientId, clientSecret, redirectUri);
// 构建 Access-Token
AccessTokenModel token = oauth2Template.generateAccessToken(code);
AccessTokenModel accessTokenModel = oauth2Template.generateAccessToken(code);
// 返回
return SaResult.data(token.toLineMap());
return SaOAuth2Manager.getDataResolver().buildTokenReturnValue(accessTokenModel);
}
/**
@@ -233,9 +231,11 @@ public class SaOAuth2ServerProcessor {
// 校验参数
oauth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
// 获取新Token返回
Object data = oauth2Template.refreshAccessToken(refreshToken).toLineMap();
return SaResult.data(data);
// 获取新 Access-Token
AccessTokenModel accessTokenModel = oauth2Template.refreshAccessToken(refreshToken);
// 返回
return SaOAuth2Manager.getDataResolver().buildRefreshTokenReturnValue(accessTokenModel);
}
/**
@@ -261,7 +261,9 @@ public class SaOAuth2ServerProcessor {
// 回收 Access-Token
oauth2Template.revokeAccessToken(accessToken);
return SaResult.ok();
// 返回
return SaOAuth2Manager.getDataResolver().buildRevokeTokenReturnValue();
}
/**
@@ -271,7 +273,6 @@ public class SaOAuth2ServerProcessor {
public Object doLogin() {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
return cfg.getDoLoginHandle().apply(req.getParamNotNull(Param.name), req.getParamNotNull(Param.pwd));
@@ -330,7 +331,7 @@ public class SaOAuth2ServerProcessor {
AccessTokenModel at = oauth2Template.generateAccessToken(ra, true);
// 6、返回 Access-Token
return SaResult.data(at.toLineMap());
return SaOAuth2Manager.getDataResolver().buildPasswordReturnValue(at);
}
/**
@@ -340,8 +341,6 @@ public class SaOAuth2ServerProcessor {
public Object clientToken() {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// 获取参数
String clientId = req.getParamNotNull(Param.client_id);
@@ -354,11 +353,11 @@ public class SaOAuth2ServerProcessor {
// 校验 ClientSecret
oauth2Template.checkClientSecret(clientId, clientSecret);
// 返回 Client-Token
// 生成
ClientTokenModel ct = oauth2Template.generateClientToken(clientId, scope);
// 返回 Client-Token
return SaResult.data(ct.toLineMap());
// 返回
return SaOAuth2Manager.getDataResolver().buildClientTokenReturnValue(ct);
}
/**