优化自定义 scope 时的扩展参数处理逻辑

This commit is contained in:
click33 2024-08-18 20:22:20 +08:00
parent c03bccd956
commit f0c2949539
22 changed files with 268 additions and 143 deletions

View File

@ -1,7 +1,7 @@
package com.pj.oauth2; package com.pj.oauth2;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader; import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.data.model.SaClientModel; import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.secure.SaSecureUtil; import cn.dev33.satoken.secure.SaSecureUtil;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -93,6 +93,15 @@ public class SaOAuth2Consts {
public static String Bearer = "Bearer"; public static String Bearer = "Bearer";
} }
/**
* 扩展字段
*/
public static final class ExtraField {
public static String openid = "openid";
public static String userid = "userid";
public static String id_token = "id_token";
}
/** 表示OK的返回结果 */ /** 表示OK的返回结果 */
public static final String OK = "ok"; public static final String OK = "ok";

View File

@ -19,11 +19,12 @@ import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel; import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.CodeModel; import cn.dev33.satoken.oauth2.data.model.CodeModel;
import cn.dev33.satoken.oauth2.data.model.RefreshTokenModel; import cn.dev33.satoken.oauth2.data.model.RefreshTokenModel;
import cn.dev33.satoken.oauth2.data.model.SaClientModel; import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy; import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
import cn.dev33.satoken.util.SaFoxUtil; import cn.dev33.satoken.util.SaFoxUtil;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
/** /**
@ -79,6 +80,7 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
at.scopes = cm.scopes; at.scopes = cm.scopes;
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(cm.clientId); SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(cm.clientId);
at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000); at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000);
at.extraData = new LinkedHashMap<>();
return at; return at;
} }
@ -94,10 +96,10 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
rt.clientId = at.clientId; rt.clientId = at.clientId;
rt.loginId = at.loginId; rt.loginId = at.loginId;
rt.scopes = at.scopes; rt.scopes = at.scopes;
rt.openid = at.openid;
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(at.clientId); SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(at.clientId);
rt.expiresTime = System.currentTimeMillis() + (clientModel.getRefreshTokenTimeout() * 1000); rt.expiresTime = System.currentTimeMillis() + (clientModel.getRefreshTokenTimeout() * 1000);
// 改变at属性 rt.extraData = new LinkedHashMap<>(at.extraData);
// 改变 at 属性
at.refreshToken = rt.refreshToken; at.refreshToken = rt.refreshToken;
at.refreshExpiresTime = rt.expiresTime; at.refreshExpiresTime = rt.expiresTime;
return rt; return rt;
@ -116,7 +118,7 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
at.clientId = rt.clientId; at.clientId = rt.clientId;
at.loginId = rt.loginId; at.loginId = rt.loginId;
at.scopes = rt.scopes; at.scopes = rt.scopes;
at.openid = rt.openid; at.extraData = new LinkedHashMap<>(rt.extraData);
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(rt.clientId); SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(rt.clientId);
at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000); at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000);
at.refreshExpiresTime = rt.expiresTime; at.refreshExpiresTime = rt.expiresTime;
@ -137,7 +139,7 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
newRt.clientId = rt.clientId; newRt.clientId = rt.clientId;
newRt.scopes = rt.scopes; newRt.scopes = rt.scopes;
newRt.loginId = rt.loginId; newRt.loginId = rt.loginId;
newRt.openid = rt.openid; newRt.extraData = new LinkedHashMap<>(rt.extraData);
return newRt; return newRt;
} }

View File

@ -18,8 +18,7 @@ package cn.dev33.satoken.oauth2.data.generate;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel; import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel; import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.data.model.CodeModel; import cn.dev33.satoken.oauth2.data.model.CodeModel;
import cn.dev33.satoken.oauth2.data.model.RequestAuthModel; import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.util.SaFoxUtil;
import java.util.List; import java.util.List;
@ -31,8 +30,6 @@ import java.util.List;
*/ */
public interface SaOAuth2DataGenerate { public interface SaOAuth2DataGenerate {
// ------------------- generate 构建数据
/** /**
* 构建ModelCode授权码 * 构建ModelCode授权码
* @param ra 请求参数Model * @param ra 请求参数Model

View File

@ -20,6 +20,8 @@ import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.dao.SaOAuth2Dao; import cn.dev33.satoken.oauth2.dao.SaOAuth2Dao;
import cn.dev33.satoken.oauth2.data.convert.SaOAuth2DataConverter; import cn.dev33.satoken.oauth2.data.convert.SaOAuth2DataConverter;
import cn.dev33.satoken.oauth2.data.model.*; import cn.dev33.satoken.oauth2.data.model.*;
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode; import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy; import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
@ -34,7 +36,6 @@ import java.util.List;
* @since 1.39.0 * @since 1.39.0
*/ */
public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate { public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
// ------------------- generate 构建数据
/** /**
* 构建ModelCode授权码 * 构建ModelCode授权码
@ -161,7 +162,8 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
// 2生成 新Access-Token // 2生成 新Access-Token
String newAtValue = SaOAuth2Strategy.instance.createAccessToken.execute(ra.clientId, ra.loginId, ra.scopes); String newAtValue = SaOAuth2Strategy.instance.createAccessToken.execute(ra.clientId, ra.loginId, ra.scopes);
AccessTokenModel at = new AccessTokenModel(newAtValue, ra.clientId, ra.loginId, ra.scopes); AccessTokenModel at = new AccessTokenModel(newAtValue, ra.clientId, ra.loginId, ra.scopes);
at.openid = SaOAuth2Manager.getDataLoader().getOpenid(ra.clientId, ra.loginId); // TODO 此处的 openid 应该怎么加载
// at.openid = SaOAuth2Manager.getDataLoader().getOpenid(ra.clientId, ra.loginId);
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(ra.clientId); SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(ra.clientId);
at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000); at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000);

View File

@ -15,11 +15,8 @@
*/ */
package cn.dev33.satoken.oauth2.data.loader; package cn.dev33.satoken.oauth2.data.loader;
import cn.dev33.satoken.oauth2.data.model.SaClientModel; import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.util.SaFoxUtil;
import java.util.List;
/** /**
* Sa-Token OAuth2 数据加载器 * Sa-Token OAuth2 数据加载器

View File

@ -16,8 +16,6 @@
package cn.dev33.satoken.oauth2.data.model; package cn.dev33.satoken.oauth2.data.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -60,17 +58,19 @@ public class AccessTokenModel implements Serializable {
* 账号id * 账号id
*/ */
public Object loginId; public Object loginId;
/**
* 开放账号id
*/
public String openid;
/** /**
* 授权范围 * 授权范围
*/ */
public List<String> scopes; public List<String> scopes;
/**
* 扩展数据
*/
public Map<String, Object> extraData;
public AccessTokenModel() {} public AccessTokenModel() {}
/** /**
@ -143,15 +143,6 @@ public class AccessTokenModel implements Serializable {
return this; return this;
} }
public String getOpenid() {
return openid;
}
public AccessTokenModel setOpenid(String openid) {
this.openid = openid;
return this;
}
public List<String> getScopes() { public List<String> getScopes() {
return scopes; return scopes;
} }
@ -161,18 +152,27 @@ public class AccessTokenModel implements Serializable {
return this; return this;
} }
public Map<String, Object> getExtraData() {
return extraData;
}
public AccessTokenModel setExtraData(Map<String, Object> extraData) {
this.extraData = extraData;
return this;
}
@Override @Override
public String toString() { public String toString() {
return "AccessTokenModel [accessToken=" + accessToken + ", refreshToken=" + refreshToken return "AccessTokenModel [accessToken=" + accessToken + ", refreshToken=" + refreshToken
+ ", accessTokenTimeout=" + expiresTime + ", refreshTokenTimeout=" + refreshExpiresTime + ", accessTokenTimeout=" + expiresTime + ", refreshTokenTimeout=" + refreshExpiresTime
+ ", clientId=" + clientId + ", scopes=" + scopes + ", openid=" + openid + "]"; + ", clientId=" + clientId + ", scopes=" + scopes + ", extraData=" + extraData + "]";
} }
// 追加只读属性 // 追加只读属性
/** /**
* 获取 Access-Token 的剩余有效期 * 获取 Access-Token 的剩余有效期
* @return see note * @return /
*/ */
public long getExpiresIn() { public long getExpiresIn() {
long s = (expiresTime - System.currentTimeMillis()) / 1000; long s = (expiresTime - System.currentTimeMillis()) / 1000;
@ -181,28 +181,11 @@ public class AccessTokenModel implements Serializable {
/** /**
* 获取 Refresh-Token 的剩余有效期 * 获取 Refresh-Token 的剩余有效期
* @return see note * @return /
*/ */
public long getRefreshExpiresIn() { public long getRefreshExpiresIn() {
long s = (refreshExpiresTime - System.currentTimeMillis()) / 1000; long s = (refreshExpiresTime - System.currentTimeMillis()) / 1000;
return s < 1 ? -2 : s; return s < 1 ? -2 : s;
} }
/**
* 将所有属性转换为下划线形式的Map
* @return 属性转Map
*/
@Deprecated
public Map<String, Object> toLineMap() {
Map<String, Object> map = new LinkedHashMap<>();
map.put("access_token", accessToken);
map.put("refresh_token", refreshToken);
map.put("expires_in", getExpiresIn());
map.put("refresh_expires_in", getRefreshExpiresIn());
map.put("client_id", clientId);
map.put("scopes", scopes);
map.put("openid", openid);
return map;
}
} }

View File

@ -16,7 +16,6 @@
package cn.dev33.satoken.oauth2.data.model; package cn.dev33.satoken.oauth2.data.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -50,6 +49,57 @@ public class ClientTokenModel implements Serializable {
*/ */
public List<String> scopes; public List<String> scopes;
/**
* 扩展数据
*/
public Map<String, Object> extraData;
public String getClientToken() {
return clientToken;
}
public ClientTokenModel setClientToken(String clientToken) {
this.clientToken = clientToken;
return this;
}
public long getExpiresTime() {
return expiresTime;
}
public ClientTokenModel setExpiresTime(long expiresTime) {
this.expiresTime = expiresTime;
return this;
}
public String getClientId() {
return clientId;
}
public ClientTokenModel setClientId(String clientId) {
this.clientId = clientId;
return this;
}
public List<String> getScopes() {
return scopes;
}
public ClientTokenModel setScopes(List<String> scopes) {
this.scopes = scopes;
return this;
}
public Map<String, Object> getExtraData() {
return extraData;
}
public ClientTokenModel setExtraData(Map<String, Object> extraData) {
this.extraData = extraData;
return this;
}
public ClientTokenModel() {} public ClientTokenModel() {}
/** /**
@ -64,35 +114,25 @@ public class ClientTokenModel implements Serializable {
this.clientId = clientId; this.clientId = clientId;
this.scopes = scopes; this.scopes = scopes;
} }
@Override @Override
public String toString() { public String toString() {
return "ClientTokenModel [clientToken=" + clientToken + ", expiresTime=" + expiresTime + ", clientId=" return "ClientTokenModel{" +
+ clientId + ", scopes=" + scopes + "]"; "clientToken='" + clientToken + '\'' +
", expiresTime=" + expiresTime +
", clientId='" + clientId + '\'' +
", scopes=" + scopes +
", extraData=" + extraData +
'}';
} }
/** /**
* 获取 Client-Token 的剩余有效期 * 获取 Client-Token 的剩余有效期
* @return see note * @return /
*/ */
public long getExpiresIn() { public long getExpiresIn() {
long s = (expiresTime - System.currentTimeMillis()) / 1000; long s = (expiresTime - System.currentTimeMillis()) / 1000;
return s < 1 ? -2 : s; return s < 1 ? -2 : s;
} }
/**
* 将所有属性转换为下划线形式的Map
* @return 属性转Map
*/
@Deprecated
public Map<String, Object> toLineMap() {
Map<String, Object> map = new LinkedHashMap<>();
map.put("client_token", clientToken);
map.put("expires_in", getExpiresIn());
map.put("client_id", clientId);
map.put("scopes", scopes);
return map;
}
} }

View File

@ -17,6 +17,7 @@ package cn.dev33.satoken.oauth2.data.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Model: Refresh-Token * Model: Refresh-Token
@ -42,11 +43,6 @@ public class RefreshTokenModel implements Serializable {
* 应用id * 应用id
*/ */
public String clientId; public String clientId;
/**
* 授权范围
*/
public List<String> scopes;
/** /**
* 对应账号id * 对应账号id
@ -54,9 +50,15 @@ public class RefreshTokenModel implements Serializable {
public Object loginId; public Object loginId;
/** /**
* 对应账号id * 授权范围
*/ */
public String openid; public List<String> scopes;
/**
* 扩展数据
*/
public Map<String, Object> extraData;
public String getRefreshToken() { public String getRefreshToken() {
return refreshToken; return refreshToken;
@ -103,24 +105,24 @@ public class RefreshTokenModel implements Serializable {
return this; return this;
} }
public String getOpenid() { public Map<String, Object> getExtraData() {
return openid; return extraData;
} }
public RefreshTokenModel setOpenid(String openid) { public RefreshTokenModel setExtraData(Map<String, Object> extraData) {
this.openid = openid; this.extraData = extraData;
return this; return this;
} }
@Override @Override
public String toString() { public String toString() {
return "RefreshTokenModel [refreshToken=" + refreshToken + ", expiresTime=" + expiresTime return "RefreshTokenModel [refreshToken=" + refreshToken + ", expiresTime=" + expiresTime
+ ", clientId=" + clientId + ", scopes=" + scopes + ", loginId=" + loginId + ", openid=" + openid + "]"; + ", clientId=" + clientId + ", loginId=" + loginId + ", scopes=" + scopes + ", extraData=" + extraData + "]";
} }
/** /**
* 获取 Refresh-Token 的剩余有效期 * 获取 Refresh-Token 的剩余有效期
* @return see note * @return /
*/ */
public long getExpiresIn() { public long getExpiresIn() {
long s = (expiresTime - System.currentTimeMillis()) / 1000; long s = (expiresTime - System.currentTimeMillis()) / 1000;

View File

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

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.dev33.satoken.oauth2.data.model.other; package cn.dev33.satoken.oauth2.data.model.request;
import java.io.Serializable; import java.io.Serializable;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.dev33.satoken.oauth2.data.model; package cn.dev33.satoken.oauth2.data.model.request;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@ -23,7 +23,7 @@ import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.util.SaFoxUtil; import cn.dev33.satoken.util.SaFoxUtil;
/** /**
* 请求授权参数的Model * 请求授权参数的 Model
* *
* @author click33 * @author click33
* @since 1.23.0 * @since 1.23.0

View File

@ -18,7 +18,8 @@ package cn.dev33.satoken.oauth2.data.resolver;
import cn.dev33.satoken.context.model.SaRequest; import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel; import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel; import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.data.model.other.ClientIdAndSecretModel; import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.data.model.request.ClientIdAndSecretModel;
import cn.dev33.satoken.util.SaResult; import cn.dev33.satoken.util.SaResult;
import java.util.Map; import java.util.Map;
@ -41,6 +42,14 @@ public interface SaOAuth2DataResolver {
*/ */
ClientIdAndSecretModel readClientIdAndSecret(SaRequest request); ClientIdAndSecretModel readClientIdAndSecret(SaRequest request);
/**
* 数据读取从请求对象中构建 RequestAuthModel
* @param req SaRequest对象
* @param loginId 账号id
* @return RequestAuthModel对象
*/
RequestAuthModel readRequestAuthModel(SaRequest req, Object loginId);
/** /**
* 构建返回值: 获取 token * 构建返回值: 获取 token

View File

@ -22,7 +22,8 @@ import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.TokenType; import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.TokenType;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel; import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel; import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.data.model.other.ClientIdAndSecretModel; import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.data.model.request.ClientIdAndSecretModel;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.util.SaFoxUtil; import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult; import cn.dev33.satoken.util.SaResult;
@ -40,7 +41,6 @@ import java.util.Map;
*/ */
public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver { public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
/** /**
* 数据读取从请求对象中读取 ClientIdSecret如果获取不到则抛出异常 * 数据读取从请求对象中读取 ClientIdSecret如果获取不到则抛出异常
* *
@ -71,6 +71,24 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
throw new SaOAuth2Exception("请提供 client 信息"); throw new SaOAuth2Exception("请提供 client 信息");
} }
/**
* 数据读取从请求对象中构建 RequestAuthModel
*/
@Override
public RequestAuthModel readRequestAuthModel(SaRequest req, Object loginId) {
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = req.getParamNotNull(SaOAuth2Consts.Param.client_id);
ra.responseType = req.getParamNotNull(SaOAuth2Consts.Param.response_type);
ra.redirectUri = req.getParamNotNull(SaOAuth2Consts.Param.redirect_uri);
ra.state = req.getParam(SaOAuth2Consts.Param.state);
// 数据解析
String scope = req.getParam(SaOAuth2Consts.Param.scope, "");
ra.scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
ra.loginId = loginId;
return ra;
}
/** /**
* 构建返回值: 获取 token * 构建返回值: 获取 token
*/ */
@ -84,7 +102,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
map.put("refresh_expires_in", at.getRefreshExpiresIn()); map.put("refresh_expires_in", at.getRefreshExpiresIn());
map.put("client_id", at.clientId); map.put("client_id", at.clientId);
map.put("scope", SaOAuth2Manager.getDataConverter().convertScopeListToString(at.scopes)); map.put("scope", SaOAuth2Manager.getDataConverter().convertScopeListToString(at.scopes));
map.put("openid", at.openid); map.putAll(at.extraData);
return SaResult.ok().setMap(map); return SaResult.ok().setMap(map);
} }
@ -99,9 +117,9 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
map.put("expires_in", ct.getExpiresIn()); map.put("expires_in", ct.getExpiresIn());
map.put("client_id", ct.clientId); map.put("client_id", ct.clientId);
map.put("scope", SaOAuth2Manager.getDataConverter().convertScopeListToString(ct.scopes)); map.put("scope", SaOAuth2Manager.getDataConverter().convertScopeListToString(ct.scopes));
map.putAll(ct.extraData);
return SaResult.ok().setMap(map); return SaResult.ok().setMap(map);
} }
} }

View File

@ -26,8 +26,12 @@ import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.GrantType;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Param; import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Param;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.ResponseType; import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.ResponseType;
import cn.dev33.satoken.oauth2.data.generate.SaOAuth2DataGenerate; import cn.dev33.satoken.oauth2.data.generate.SaOAuth2DataGenerate;
import cn.dev33.satoken.oauth2.data.model.*; import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.other.ClientIdAndSecretModel; import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.data.model.CodeModel;
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.data.model.request.ClientIdAndSecretModel;
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode; import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.template.SaOAuth2Template; import cn.dev33.satoken.oauth2.template.SaOAuth2Template;
@ -148,8 +152,8 @@ public class SaOAuth2ServerProcessor {
return cfg.notLoginView.get(); return cfg.notLoginView.get();
} }
// 2构建请求Model // 2构建请求 Model
RequestAuthModel ra = oauth2Template.generateRequestAuth(req, getStpLogic().getLoginId()); RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, getStpLogic().getLoginId());
// 3校验重定向域名是否合法 // 3校验重定向域名是否合法
oauth2Template.checkRightUrl(ra.clientId, ra.redirectUri); oauth2Template.checkRightUrl(ra.clientId, ra.redirectUri);

View File

@ -32,9 +32,9 @@ public final class CommonScope {
public static final String OPENID = "openid"; public static final String OPENID = "openid";
/** /**
* 获取用户信息 * 获取 userid
*/ */
public static final String USERINFO = "userinfo"; public static final String USERID = "userid";
/** /**
* 获取 id_token * 获取 id_token

View File

@ -0,0 +1,44 @@
/*
* 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.scope.handler;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.scope.CommonScope;
/**
* id_token 权限处理器 AccessToken 扩展参数中追加 id_token 字段
*
* @author click33
* @since 1.39.0
*/
public class OidcScopeHandler implements SaOAuth2ScopeAbstractHandler {
public String getHandlerScope() {
return CommonScope.OIDC;
}
@Override
public void workAccessToken(AccessTokenModel at) {
// TODO 追加参数 id_token
}
@Override
public void workClientToken(ClientTokenModel ct) {
}
}

View File

@ -16,29 +16,26 @@
package cn.dev33.satoken.oauth2.scope.handler; package cn.dev33.satoken.oauth2.scope.handler;
import cn.dev33.satoken.oauth2.SaOAuth2Manager; import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel; import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel; import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.scope.CommonScope; import cn.dev33.satoken.oauth2.scope.CommonScope;
/** /**
* OpenId 权限处理器 * OpenId 权限处理器 AccessToken 扩展参数中追加 openid 字段
* *
* @author click33 * @author click33
* @since 1.39.0 * @since 1.39.0
*/ */
public class OpenIdScopeHandler implements SaOAuth2ScopeAbstractHandler { public class OpenIdScopeHandler implements SaOAuth2ScopeAbstractHandler {
/**
* 获取所要处理的权限
*/
public String getHandlerScope() { public String getHandlerScope() {
return CommonScope.OPENID; return CommonScope.OPENID;
} }
@Override @Override
public void workAccessToken(AccessTokenModel at) { public void workAccessToken(AccessTokenModel at) {
System.out.println("追加 openid " + at.accessToken); at.extraData.put(SaOAuth2Consts.ExtraField.openid, SaOAuth2Manager.getDataLoader().getOpenid(at.clientId, at.loginId));
at.openid = SaOAuth2Manager.getDataLoader().getOpenid(at.clientId, at.loginId);
} }
@Override @Override

View File

@ -0,0 +1,45 @@
/*
* 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.scope.handler;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.scope.CommonScope;
/**
* UserId 权限处理器 AccessToken 扩展参数中追加 userid 字段
*
* @author click33
* @since 1.39.0
*/
public class UserIdScopeHandler implements SaOAuth2ScopeAbstractHandler {
public String getHandlerScope() {
return CommonScope.USERID;
}
@Override
public void workAccessToken(AccessTokenModel at) {
at.extraData.put(SaOAuth2Consts.ExtraField.userid, at.loginId);
}
@Override
public void workClientToken(ClientTokenModel ct) {
}
}

View File

@ -18,8 +18,10 @@ package cn.dev33.satoken.oauth2.strategy;
import cn.dev33.satoken.SaManager; import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.oauth2.function.strategy.*; import cn.dev33.satoken.oauth2.function.strategy.*;
import cn.dev33.satoken.oauth2.scope.CommonScope; import cn.dev33.satoken.oauth2.scope.CommonScope;
import cn.dev33.satoken.oauth2.scope.handler.OidcScopeHandler;
import cn.dev33.satoken.oauth2.scope.handler.OpenIdScopeHandler; import cn.dev33.satoken.oauth2.scope.handler.OpenIdScopeHandler;
import cn.dev33.satoken.oauth2.scope.handler.SaOAuth2ScopeAbstractHandler; import cn.dev33.satoken.oauth2.scope.handler.SaOAuth2ScopeAbstractHandler;
import cn.dev33.satoken.oauth2.scope.handler.UserIdScopeHandler;
import cn.dev33.satoken.util.SaFoxUtil; import cn.dev33.satoken.util.SaFoxUtil;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -54,6 +56,8 @@ public final class SaOAuth2Strategy {
*/ */
public void registerDefaultScopeHandler() { public void registerDefaultScopeHandler() {
scopeHandlerMap.put(CommonScope.OPENID, new OpenIdScopeHandler()); scopeHandlerMap.put(CommonScope.OPENID, new OpenIdScopeHandler());
scopeHandlerMap.put(CommonScope.USERID, new UserIdScopeHandler());
scopeHandlerMap.put(CommonScope.OIDC, new OidcScopeHandler());
} }
/** /**

View File

@ -15,11 +15,10 @@
*/ */
package cn.dev33.satoken.oauth2.template; package cn.dev33.satoken.oauth2.template;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager; import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Param;
import cn.dev33.satoken.oauth2.dao.SaOAuth2Dao; import cn.dev33.satoken.oauth2.dao.SaOAuth2Dao;
import cn.dev33.satoken.oauth2.data.model.*; import cn.dev33.satoken.oauth2.data.model.*;
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode; import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.strategy.SaStrategy; import cn.dev33.satoken.strategy.SaStrategy;
@ -119,25 +118,6 @@ public class SaOAuth2Template {
} }
} }
// ------------------- generate 构建数据
/**
* 构建Model请求Model
* @param req SaRequest对象
* @param loginId 账号id
* @return RequestAuthModel对象
*/
public RequestAuthModel generateRequestAuth(SaRequest req, Object loginId) {
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = req.getParamNotNull(Param.client_id);
ra.responseType = req.getParamNotNull(Param.response_type);
ra.redirectUri = req.getParamNotNull(Param.redirect_uri);
ra.state = req.getParam(Param.state);
// 数据解析
String scope = req.getParam(Param.scope, "");
ra.scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
ra.loginId = loginId;
return ra;
}
// ------------------- check 数据校验 // ------------------- check 数据校验
/** /**

View File

@ -15,9 +15,12 @@
*/ */
package cn.dev33.satoken.oauth2.template; package cn.dev33.satoken.oauth2.template;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager; import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.data.model.*; import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.data.model.CodeModel;
import cn.dev33.satoken.oauth2.data.model.RefreshTokenModel;
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor; import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor;
import java.util.List; import java.util.List;
@ -86,17 +89,6 @@ public class SaOAuth2Util {
SaOAuth2ServerProcessor.instance.oauth2Template.checkClientTokenScope(clientToken, scopes); SaOAuth2ServerProcessor.instance.oauth2Template.checkClientTokenScope(clientToken, scopes);
} }
// ------------------- generate 构建数据
/**
* 构建Model请求Model
* @param req SaRequest对象
* @param loginId 账号id
* @return RequestAuthModel对象
*/
public static RequestAuthModel generateRequestAuth(SaRequest req, Object loginId) {
return SaOAuth2ServerProcessor.instance.oauth2Template.generateRequestAuth(req, loginId);
}
// ------------------- 数据校验 // ------------------- 数据校验