OAuth2.0 beta ..

This commit is contained in:
click33
2021-07-17 23:48:12 +08:00
parent 742b65366a
commit 971c2860f0
46 changed files with 2160 additions and 914 deletions

View File

@@ -3,7 +3,7 @@ package cn.dev33.satoken.oauth2;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
/**
* sa-token oauth2 模块 总控类
* Sa-Token-OAuth2 模块 总控类
*
* @author kong
*

View File

@@ -1,40 +1,118 @@
package cn.dev33.satoken.oauth2.config;
import java.io.Serializable;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.util.SaResult;
/**
* sa-token oauth2 配置类 Model
* Sa-Token-OAuth2 配置类 Model
* @author kong
*
*/
public class SaOAuth2Config {
public class SaOAuth2Config implements Serializable {
/**
* 授权码默认保存的时间(单位秒) 默认五分钟
*/
private long codeTimeout = 60 * 5;
private static final long serialVersionUID = -6541180061782004705L;
/**
* access_token默认保存的时间(单位秒) 默认两个小时
*/
private long accessTokenTimeout = 60 * 60 * 2;
/** 是否打开模式授权码Authorization Code */
public Boolean isCode = true;
/**
* refresh_token默认保存的时间(单位秒) 默认30 天
*/
private long refreshTokenTimeout = 60 * 60 * 24 * 30;
/** 是否打开模式隐藏式Implicit */
public Boolean isImplicit = false;
/**
* client_token默认保存的时间(单位秒) 默认两个小时
*/
private long clientTokenTimeout = 60 * 60 * 2;
/** 是否打开模式密码式Password */
public Boolean isPassword = false;
/** 是否打开模式凭证式Client Credentials */
public Boolean isClient = false;
/** 是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token */
public Boolean isNewRefresh = false;
/** Code授权码 保存的时间(单位秒) 默认五分钟 */
public long codeTimeout = 60 * 5;
/** Access-Token 保存的时间(单位秒) 默认两个小时 */
public long accessTokenTimeout = 60 * 60 * 2;
/** Refresh-Token 保存的时间(单位秒) 默认30 天 */
public long refreshTokenTimeout = 60 * 60 * 24 * 30;
/** Client-Token 保存的时间(单位秒) 默认两个小时 */
public long clientTokenTimeout = 60 * 60 * 2;
/**
* @return isCode
*/
public Boolean getIsCode() {
return isCode;
}
/**
* @param isCode 要设置的 isCode
*/
public void setIsCode(Boolean isCode) {
this.isCode = isCode;
}
/**
* @return isImplicit
*/
public Boolean getIsImplicit() {
return isImplicit;
}
/**
* @param isImplicit 要设置的 isImplicit
*/
public void setIsImplicit(Boolean isImplicit) {
this.isImplicit = isImplicit;
}
/**
* @return isPassword
*/
public Boolean getIsPassword() {
return isPassword;
}
/**
* @param isPassword 要设置的 isPassword
*/
public void setIsPassword(Boolean isPassword) {
this.isPassword = isPassword;
}
/**
* @return isClient
*/
public Boolean getIsClient() {
return isClient;
}
/**
* @param isClient 要设置的 isClient
*/
public void setIsClient(Boolean isClient) {
this.isClient = isClient;
}
/**
* @return isNewRefresh
*/
public Boolean getIsNewRefresh() {
return isNewRefresh;
}
/**
* @param isNewRefresh 要设置的 isNewRefresh
*/
public void setIsNewRefresh(Boolean isNewRefresh) {
this.isNewRefresh = isNewRefresh;
}
/**
* @return codeTimeout
*/
@@ -100,26 +178,13 @@ public class SaOAuth2Config {
}
// -------------------- SaOAuth2Handle 所有回调函数 --------------------
/**
* OAuth-Server端未登录时返回的View
*/
public Supplier<Object> notLoginView = () -> "当前会话在OAuth-Server认证中心尚未登录";
/**
* OAuth-Server端重定向URL无效时返回的View
*/
public BiFunction<String, String, Object> invalidUrlView = (clientId, url) -> "无效重定向URL" + url;
/**
* OAuth-Server端Client请求的Scope暂未签约时返回的View
*/
public BiFunction<String, String, Object> invalidScopeView = (clientId, scope) -> "请求的Scope暂未签约";
/**
* OAuth-Server端确认授权时返回的View
*/
@@ -130,12 +195,6 @@ public class SaOAuth2Config {
*/
public BiFunction<String, String, Object> doLoginHandle = (name, pwd) -> SaResult.error();
/**
* SSO-Client端发送Http请求的处理函数
*/
public Function<String, Object> sendHttp = url -> {throw new SaTokenException("请配置Http处理器");};
/**
* @param notLoginView OAuth-Server端未登录时返回的View
* @return 对象自身
@@ -145,24 +204,6 @@ public class SaOAuth2Config {
return this;
}
/**
* @param invalidScopeView OAuth-Server端重定向URL无效时返回的View
* @return 对象自身
*/
public SaOAuth2Config setInvalidUrlView(BiFunction<String, String, Object> invalidUrlView) {
this.invalidUrlView = invalidUrlView;
return this;
}
/**
* @param invalidScopeView OAuth-Server端Client请求的Scope暂未签约时返回的View
* @return 对象自身
*/
public SaOAuth2Config setInvalidScopeView(BiFunction<String, String, Object> invalidScopeView) {
this.invalidScopeView = invalidScopeView;
return this;
}
/**
* @param confirmView OAuth-Server端确认授权时返回的View
* @return 对象自身
@@ -181,23 +222,13 @@ public class SaOAuth2Config {
return this;
}
/**
* @param sendHttp 发送Http请求的处理函数
* @return 对象自身
*/
public SaOAuth2Config setSendHttp(Function<String, Object> sendHttp) {
this.sendHttp = sendHttp;
return this;
}
@Override
public String toString() {
return "SaOAuth2Config [codeTimeout=" + codeTimeout + ", accessTokenTimeout=" + accessTokenTimeout
+ ", refreshTokenTimeout=" + refreshTokenTimeout + "]";
return "SaOAuth2Config [isCode=" + isCode + ", isImplicit=" + isImplicit + ", isPassword=" + isPassword
+ ", isClient=" + isClient + ", isNewRefresh=" + isNewRefresh + ", codeTimeout=" + codeTimeout
+ ", accessTokenTimeout=" + accessTokenTimeout + ", refreshTokenTimeout=" + refreshTokenTimeout
+ ", clientTokenTimeout=" + clientTokenTimeout + "]";
}
}

View File

@@ -12,10 +12,12 @@ public class SaOAuth2Consts {
* @author kong
*/
public static final class Api {
/** OAuth-Server端授权地址 */
public static String authorize = "/oauth2/authorize";
public static String token = "/oauth2/token";
public static String refresh = "/oauth2/refresh";
public static String client_token = "/oauth2/client_token";
public static String doLogin = "/oauth2/doLogin";
public static String doConfirm = "/oauth2/doConfirm";
}
/**
@@ -23,70 +25,44 @@ public class SaOAuth2Consts {
* @author kong
*/
public static final class Param {
/** authorize 的 返回值类型 */
public static String response_type = "response_type";
/** client_id 参数名称 */
public static String client_id = "client_id";
/** client_secret 参数名称 */
public static String client_secret = "client_secret";
/** redirect_uri 参数名称 */
public static String redirect_uri = "redirect_uri";
/** scope 参数名称 */
public static String scope = "scope";
/** state */
public static String state = "state";
/** code 参数名称 */
public static String code = "code";
/** token 参数名称 */
public static String token = "token";
/** grant_type 参数名称 */
public static String refresh_token = "refresh_token";
public static String grant_type = "grant_type";
public static String username = "username";
public static String password = "password";
public static String name = "name";
public static String pwd = "pwd";
}
/**
* 所有返回类型
*/
public static final class ResponseType {
public static String code = "code";
public static String token = "token";
}
/**
* 所有授权类型
*/
public static final class AuthType {
/** 方式一:授权码 */
public static String code = "code";
/** 方式二:隐藏式 */
public static String token = "token";
/** 方式三:密码式 */
public static String password = "password";
/** 方式四:凭证式 */
public static String client_credentials = "client_credentials";
public static final class GrantType {
public static String authorization_code = "authorization_code";
public static String refresh_token = "refresh_token";
public static String password = "password";
public static String client_credentials = "client_credentials";
}
/**
* 在保存授权码时用到的key
*/
public static final String UNLIMITED_DOMAIN = "*";
/** 表示OK的返回结果 */
public static final String OK = "ok";
/** 表示请求没有得到任何有效处理 */
public static final String NOT_HANDLE = "not handle";
/** 表示请求没有得到任何有效处理 {msg: "not handle"} */
public static final String NOT_HANDLE = "{\"msg\": \"not handle\"}";
}

View File

@@ -5,12 +5,15 @@ import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.AuthType;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Api;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.GrantType;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Param;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.ResponseType;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.model.CodeModel;
import cn.dev33.satoken.oauth2.model.RequestAuthModel;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
@@ -20,106 +23,236 @@ import cn.dev33.satoken.util.SaResult;
*
*/
public class SaOAuth2Handle {
/**
* 处理Server端请求
* 处理Server端请求 路由分发
* @return 处理结果
*/
public static Object authorize() {
public static Object serverRequest() {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
// match(Api.authorize) &&
// 授权
if(req.isParam(Param.response_type, AuthType.code)) {
// 1、构建请求Model TODO 貌似这个RequestAuthModel对象也可以省略掉
RequestAuthModel ra = SaOAuth2Util.generateRequestAuth(req, StpUtil.getLoginId());
// 2、如果尚未登录, 则先去登录
if(StpUtil.isLogin() == false) {
return cfg.notLoginView.get();
}
// 3、判断重定向域名的格式是否合法
boolean isRigh = SaOAuth2Util.isRightUrl(ra.clientId, ra.redirectUri);
if(isRigh == false) {
return cfg.invalidUrlView.apply(ra.clientId, ra.redirectUri);
}
// 4、判断此次申请的Scope该Client是否已经签约
boolean isContract = SaOAuth2Util.isContract(ra.clientId, ra.scope);
if(isContract == false) {
return cfg.invalidScopeView.apply(ra.clientId, ra.scope);
}
// 5、判断此次申请的Scope该用户是否已经授权过了
boolean isGrant = SaOAuth2Util.isGrant(StpUtil.getLoginId(), ra.clientId, ra.scope);
if(isGrant == false) {
// 如果尚未授权,则转到授权页面,开始授权操作
return cfg.confirmView.apply(ra.clientId, ra.scope);
}
// ------------------ 路由分发 ------------------
// 模式一Code授权码
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.code) && cfg.isCode) {
return authorize(req, res, cfg);
}
// 6、开始重定向授权下放code
// Code授权码 获取 Access-Token
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.authorization_code)) {
return token(req, res, cfg);
}
// Refresh-Token 刷新 Access-Token
if(req.isPath(Api.refresh) && req.isParam(Param.grant_type, GrantType.refresh_token)) {
return refreshToken(req);
}
// doLogin 登录接口
if(req.isPath(Api.doLogin)) {
return doLogin(req, res, cfg);
}
// doConfirm 确认授权接口
if(req.isPath(Api.doConfirm)) {
return doConfirm(req);
}
// 模式二:隐藏式
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token) && cfg.isImplicit) {
return authorize(req, res, cfg);
}
// 模式三:密码式
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password) && cfg.isPassword) {
return password(req, res, cfg);
}
// 模式四:凭证式
if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials) && cfg.isClient) {
return clientToken(req, res, cfg);
}
// 默认返回
return SaOAuth2Consts.NOT_HANDLE;
}
/**
* 模式一Code授权码 / 模式二:隐藏式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object authorize(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 1、如果尚未登录, 则先去登录
if(StpUtil.isLogin() == false) {
return cfg.notLoginView.get();
}
// 2、构建请求Model
RequestAuthModel ra = SaOAuth2Util.generateRequestAuth(req, StpUtil.getLoginId());
// 3、校验重定向域名是否合法
SaOAuth2Util.checkRightUrl(ra.clientId, ra.redirectUri);
// 4、校验此次申请的Scope该Client是否已经签约
SaOAuth2Util.checkContract(ra.clientId, ra.scope);
// 5、判断如果此次申请的Scope该用户尚未授权则转到授权页面
boolean isGrant = SaOAuth2Util.isGrant(ra.loginId, ra.clientId, ra.scope);
if(isGrant == false) {
return cfg.confirmView.apply(ra.clientId, ra.scope);
}
// 6、判断授权类型
// 如果是 授权码式开始重定向授权下放code
if(ResponseType.code.equals(ra.responseType)) {
CodeModel codeModel = SaOAuth2Util.generateCode(ra);
String redirectUri = SaOAuth2Util.buildRedirectUri(ra.redirectUri, codeModel.code, ra.state);
return res.redirect(redirectUri);
}
// 默认返回
return SaOAuth2Consts.NOT_HANDLE;
}
/**
* 获取Token
* @return
*/
public static Object token() {
// 获取变量
SaRequest req = SaHolder.getRequest();
// SaResponse res = SaHolder.getResponse();
// SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// 根据code换token
if(req.isParam(Param.grant_type, AuthType.authorization_code)) {
System.out.println("------------获取token");
// 获取参数
String code = req.getParamNotNull(Param.code); // code码
String clientId = req.getParamNotNull(Param.client_id); // 应用id
String clientSecret = req.getParamNotNull(Param.client_secret); // 应用秘钥
String redirectUri = req.getParam(Param.redirect_uri); // 应用秘钥
// 校验参数
SaOAuth2Util.checkCodeIdSecret(code, clientId, clientSecret, redirectUri);
// 构建 access_token
AccessTokenModel token = SaOAuth2Util.generateAccessToken(code);
// 返回
return SaResult.data(token.toLineMap());
// 如果是 隐藏式,则:开始重定向授权,下放 token
if(ResponseType.token.equals(ra.responseType)) {
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, false);
String redirectUri = SaOAuth2Util.buildImplicitRedirectUri(ra.redirectUri, at.accessToken, ra.state);
return res.redirect(redirectUri);
}
// 默认返回
return SaOAuth2Consts.NOT_HANDLE;
throw new SaOAuth2Exception("无效response_type: " + ra.responseType);
}
/**
* Code授权码 获取 Access-Token
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object token(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 获取参数
String code = req.getParamNotNull(Param.code);
String clientId = req.getParamNotNull(Param.client_id);
String clientSecret = req.getParamNotNull(Param.client_secret);
String redirectUri = req.getParam(Param.redirect_uri);
// 校验参数
SaOAuth2Util.checkGainTokenParam(code, clientId, clientSecret, redirectUri);
// 构建 Access-Token
AccessTokenModel token = SaOAuth2Util.generateAccessToken(code);
// 返回
return SaResult.data(token.toLineMap());
}
/**
* 路由匹配算法
* @param pattern 路由表达式
* @return 是否可以匹配
* Refresh-Token 刷新 Access-Token
* @param req 请求对象
* @return 处理结果
*/
static boolean match(String pattern) {
return SaRouter.isMatch(pattern, SaHolder.getRequest().getRequestPath());
public static Object refreshToken(SaRequest req) {
// 获取参数
String clientId = req.getParamNotNull(Param.client_id);
String clientSecret = req.getParamNotNull(Param.client_secret);
String refreshToken = req.getParamNotNull(Param.refresh_token);
// 校验参数
SaOAuth2Util.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
// 获取新Token返回
Object data = SaOAuth2Util.saOAuth2Template.refreshAccessToken(refreshToken).toLineMap();
return SaResult.data(data);
}
/**
* doLogin 登录接口
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object doLogin(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
return cfg.doLoginHandle.apply(req.getParamNotNull(Param.name), req.getParamNotNull("pwd"));
}
/**
* doConfirm 确认授权接口
* @param req 请求对象
* @return 处理结果
*/
public static Object doConfirm(SaRequest req) {
String clientId = req.getParamNotNull(Param.client_id);
String scope = req.getParamNotNull(Param.scope);
Object loginId = StpUtil.getLoginId();
SaOAuth2Util.saveGrantScope(clientId, loginId, scope);
return SaResult.ok();
}
/**
* 模式三:密码式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object password(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 1、获取请求参数
String username = req.getParamNotNull(Param.username);
String password = req.getParamNotNull(Param.password);
String clientId = req.getParamNotNull(Param.client_id);
// 2、校验client_id
SaOAuth2Util.checkClientModel(clientId);
// 3、防止因前端误传token造成逻辑干扰
SaHolder.getStorage().set(StpUtil.stpLogic.splicingKeyJustCreatedSave(), "no-token");
// 4、调用API 开始登录,如果没能成功登录,则直接退出
Object retObj = cfg.doLoginHandle.apply(username, password);
if(StpUtil.isLogin() == false) {
return retObj;
}
// 5、构建 ra对象
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = clientId;
ra.loginId = StpUtil.getLoginId();
ra.scope = req.getParam(Param.scope, "");
// 6、生成 Access-Token
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, true);
// 7、返回 Access-Token
return SaResult.data(at.toLineMap());
}
/**
* 模式四:凭证式
* @return 处理结果
*/
public static Object clientToken(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 获取参数
String clientId = req.getParamNotNull(Param.client_id);
String clientSecret = req.getParamNotNull(Param.client_secret);
String scope = req.getParam(Param.scope);
// 校验 ClientSecret
SaOAuth2Util.checkClientSecret(clientId, clientSecret);
// 返回 Client-Token
ClientTokenModel ct = SaOAuth2Util.generateClientToken(clientId, scope);
// 返回 Client-Token
return SaResult.data(ct.toLineMap());
}
}

View File

@@ -1,199 +1,39 @@
package cn.dev33.satoken.oauth2.logic;
import java.util.List;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.model.CodeModel;
import cn.dev33.satoken.oauth2.model.RefreshTokenModel;
import cn.dev33.satoken.oauth2.model.RequestAuthModel;
import cn.dev33.satoken.oauth2.model.SaClientModel;
/**
* sa-token-oauth2 模块 静态类接口转发, 方便调用
* Sa-Token-OAuth2 模块 工具类
* @author kong
*
*
*/
public class SaOAuth2Util {
/**
* 模板代码对象
*/
public static SaOAuth2Template saOAuth2Template = new SaOAuth2Template();
/**
* 根据 SaRequest 对象创建 RequestAuthModel
* @param req SaRequest对象
* @param loginId 账号id
* @return RequestAuthModel对象
*/
public static RequestAuthModel generateRequestAuth(SaRequest req, Object loginId) {
return saOAuth2Template.generateRequestAuth(req, loginId);
}
// ---------------------------------------------- 分界线 -----------------------------------------------------
// ------------------- 获取数据
// ------------------- 资源获取
/**
* 返回此平台所有权限集合
* @return 此平台所有权限名称集合
*/
public static List<String> getAppScopeList() {
return saOAuth2Template.getAppScopeList();
}
/**
* 返回指定Client签约的所有Scope名称集合
* @param clientId 应用id
* @return Scope集合
*/
public static List<String> getClientScopeList(String clientId) {
return saOAuth2Template.getClientScopeList(clientId);
}
/**
* 获取指定 LoginId 对指定 Client 已经授权过的所有 Scope
* @param clientId 应用id
* @param loginId 账号id
* @return Scope集合
*/
public static List<String> getGrantScopeList(Object loginId, String clientId) {
return saOAuth2Template.getGrantScopeList(loginId, clientId);
}
// ------------------- 数据校验
/**
* [OK] 判断该Client是否签约了指定的Scope
* 根据id获取Client信息, 如果Client为空则抛出异常
* @param clientId 应用id
* @param scope 权限
* @return ClientModel
*/
public static boolean isContract(String clientId, String scope) {
return saOAuth2Template.isContract(clientId, scope);
public static SaClientModel checkClientModel(String clientId) {
return saOAuth2Template.checkClientModel(clientId);
}
/**
* 指定 loginId 是否对一个 Client 授权给了指定 Scope
* @param clientId 应用id
* @param scope 权限
* @param loginId 账号id
* @return 是否已经授权
*/
public static boolean isGrant(Object loginId, String clientId, String scope) {
return saOAuth2Template.isGrant(loginId, clientId, scope);
}
/**
* [OK] 指定Client使用指定url作为回调地址是否合法
* @param clientId 应用id
* @param url 指定url
* @return 是否合法
*/
public static boolean isRightUrl(String clientId, String url) {
return saOAuth2Template.isRightUrl(clientId, url);
}
/**
* [OK 方法名改一下]校验code、clientId、clientSecret 三者是否正确
* @param code 授权码
* @param clientId 应用id
* @param clientSecret 秘钥
* @param redirectUri 秘钥
* @return CodeModel对象
*/
public static CodeModel checkCodeIdSecret(String code, String clientId, String clientSecret, String redirectUri) {
return saOAuth2Template.checkCodeIdSecret(code, clientId, clientSecret, redirectUri);
}
/**
* [default] 校验access_token、clientId、clientSecret 三者是否正确
* @param accessToken access_token
* @param clientId 应用id
* @param clientSecret 秘钥
* @return AccessTokenModel对象
*/
public static AccessTokenModel checkTokenIdSecret(String accessToken, String clientId, String clientSecret) {
return saOAuth2Template.checkTokenIdSecret(accessToken, clientId, clientSecret);
}
// ------------------- 逻辑相关
/**
* [OK] 根据参数生成一个授权码并返回
* @param authModel 请求授权参数Model
* @return 授权码Model
*/
public static CodeModel generateCode(RequestAuthModel authModel) {
return saOAuth2Template.generateCode(authModel);
}
/**
* 根据授权码获得授权码Model
* @param code 授权码
* @return 授权码Model
*/
public static CodeModel getCode(String code) {
return saOAuth2Template.getCode(code);
}
/**
* [default] 删除一个授权码
* @param code 授权码
*/
public static void deleteCode(String code) {
saOAuth2Template.deleteCode(code);
}
/**
* 根据授权码Model生成一个access_token
* @param codeModel 授权码Model
* @return AccessTokenModel
*/
public static AccessTokenModel generateAccessToken(String code) {
return saOAuth2Template.generateAccessToken(code);
}
/**
* [default] 根据 access_token 获得其Model详细信息
* @param accessToken access_token
* @return AccessTokenModel (授权码Model)
*/
public static AccessTokenModel getAccessToken(String accessToken) {
return saOAuth2Template.getAccessToken(accessToken);
}
/**
* 根据 refresh_token 生成一个新的 access_token
* @param refreshToken refresh_token
* @return 新的 access_token
*/
public static AccessTokenModel refreshAccessToken(String refreshToken) {
return saOAuth2Template.refreshAccessToken(refreshToken);
}
/**
* [default] 根据 refresh_token 获得其Model详细信息
* @param refreshToken refresh_token
* @return RefreshToken
*/
public static RefreshTokenModel getRefreshToken(String refreshToken) {
return saOAuth2Template.getRefreshToken(refreshToken);
}
/**
* [default] 获取 access_token 所代表的LoginId
* 获取 access_token 所代表的LoginId
* @param accessToken access_token
* @return LoginId
*/
@@ -202,27 +42,85 @@ public class SaOAuth2Util {
}
/**
* 构建:AccessToken Model (根据RequestAuthModel) 用于隐藏式
* @param ra 请求授权参数Model
* @return 授权码Model
* 获取 Access-Token如果AccessToken为空则抛出异常
* @param accessToken .
* @return .
*/
public static AccessTokenModel generateAccessToken(RequestAuthModel ra) {
return saOAuth2Template.generateAccessToken(ra);
public static AccessTokenModel checkAccessToken(String accessToken) {
return saOAuth2Template.checkAccessToken(accessToken);
}
/**
* 获取 Client-Token如果ClientToken为空则抛出异常
* @param clientToken .
* @return .
*/
public static ClientTokenModel checkClientToken(String clientToken) {
return saOAuth2Template.checkClientToken(clientToken);
}
// ------------------- generate 构建数据
/**
* 构建Model请求Model
* @param req SaRequest对象
* @param loginId 账号id
* @return RequestAuthModel对象
*/
public static RequestAuthModel generateRequestAuth(SaRequest req, Object loginId) {
return saOAuth2Template.generateRequestAuth(req, loginId);
}
/**
* 构建ModelCode授权码
* @param ra 请求参数Model
* @return 授权码Model
*/
public static CodeModel generateCode(RequestAuthModel ra) {
return saOAuth2Template.generateCode(ra);
}
/**
* 构建ModelAccess-Token
* @param code 授权码Model
* @return AccessToken Model
*/
public static AccessTokenModel generateAccessToken(String code) {
return saOAuth2Template.generateAccessToken(code);
}
/**
* 构建ClientToken Model
* @param ra 请求授权参数Model
* @return ClientToken-Model
* 刷新Model根据 Refresh-Token 生成一个新的 Access-Token
* @param refreshToken Refresh-Token值
* @return 新的 Access-Token
*/
public static AccessTokenModel refreshAccessToken(String refreshToken) {
return saOAuth2Template.refreshAccessToken(refreshToken);
}
/**
* 构建ModelAccess-Token (根据RequestAuthModel构建用于隐藏式 and 密码式)
* @param ra 请求参数Model
* @param isCreateRt 是否生成对应的Refresh-Token
* @return Access-Token Model
*/
public static AccessTokenModel generateAccessToken(RequestAuthModel ra, boolean isCreateRt) {
return saOAuth2Template.generateAccessToken(ra, isCreateRt);
}
/**
* 构建ModelClient-Token
* @param clientId 应用id
* @param scope 授权范围
* @return Client-Token Model
*/
public static ClientTokenModel generateClientToken(String clientId, String scope) {
return saOAuth2Template.generateClientToken(clientId, scope);
}
// ------------------- 自定义策略相关
/**
* [OK] 构建URL下放授权码URL
* 构建URL下放Code URL (Authorization Code 授权码)
* @param redirectUri 下放地址
* @param code code参数
* @param state state参数
@@ -231,16 +129,144 @@ public class SaOAuth2Util {
public static String buildRedirectUri(String redirectUri, String code, String state) {
return saOAuth2Template.buildRedirectUri(redirectUri, code, state);
}
/**
* [OK] 构建URL下放Token URL
* 构建URL下放Access-Token URL implicit 隐藏式)
* @param redirectUri 下放地址
* @param token token
* @param state state参数
* @return 构建完毕的URL
*/
public static String buildRedirectUri2(String redirectUri, String token, String state) {
return saOAuth2Template.buildRedirectUri2(redirectUri, token, state);
public static String buildImplicitRedirectUri(String redirectUri, String token, String state) {
return saOAuth2Template.buildImplicitRedirectUri(redirectUri, token, state);
}
// ------------------- 数据校验
/**
* 判断:指定 loginId 是否对一个 Client 授权给了指定 Scope
* @param loginId 账号id
* @param clientId 应用id
* @param scope 权限
* @return 是否已经授权
*/
public static boolean isGrant(Object loginId, String clientId, String scope) {
return saOAuth2Template.isGrant(loginId, clientId, scope);
}
/**
* 校验该Client是否签约了指定的Scope
* @param clientId 应用id
* @param scope 权限(多个用逗号隔开)
*/
public static void checkContract(String clientId, String scope) {
saOAuth2Template.checkContract(clientId, scope);
}
/**
* 校验该Client使用指定url作为回调地址是否合法
* @param clientId 应用id
* @param url 指定url
*/
public static void checkRightUrl(String clientId, String url) {
saOAuth2Template.checkRightUrl(clientId, url);
}
/**
* 校验clientId 与 clientSecret 是否正确
* @param clientId 应用id
* @param clientSecret 秘钥
* @return SaClientModel对象
*/
public static SaClientModel checkClientSecret(String clientId, String clientSecret) {
return saOAuth2Template.checkClientSecret(clientId, clientSecret);
}
/**
* 校验:使用 code 获取 token 时提供的参数校验
* @param code 授权码
* @param clientId 应用id
* @param clientSecret 秘钥
* @param redirectUri 重定向地址
* @return CodeModel对象
*/
public static CodeModel checkGainTokenParam(String code, String clientId, String clientSecret, String redirectUri) {
return saOAuth2Template.checkGainTokenParam(code, clientId, clientSecret, redirectUri);
}
/**
* 校验:使用 Refresh-Token 刷新 Access-Token 时提供的参数校验
* @param clientId 应用id
* @param clientSecret 秘钥
* @param refreshToken Refresh-Token
* @return CodeModel对象
*/
public static RefreshTokenModel checkRefreshTokenParam(String clientId, String clientSecret, String refreshToken) {
return saOAuth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
}
// ------------------- save 数据
/**
* 持久化:用户授权记录
* @param clientId 应用id
* @param loginId 账号id
* @param scope 权限列表(多个逗号隔开)
*/
public static void saveGrantScope(String clientId, Object loginId, String scope) {
saOAuth2Template.saveGrantScope(clientId, loginId, scope);
}
// ------------------- get 数据
/**
* 获取Code Model
* @param code .
* @return .
*/
public static CodeModel getCode(String code) {
return saOAuth2Template.getCode(code);
}
/**
* 获取Access-Token Model
* @param accessToken .
* @return .
*/
public static AccessTokenModel getAccessToken(String accessToken) {
return saOAuth2Template.getAccessToken(accessToken);
}
/**
* 获取Refresh-Token Model
* @param refreshToken .
* @return .
*/
public static RefreshTokenModel getRefreshToken(String refreshToken) {
return saOAuth2Template.getRefreshToken(refreshToken);
}
/**
* 获取Client-Token Model
* @param clientToken .
* @return .
*/
public static ClientTokenModel getClientToken(String clientToken) {
return saOAuth2Template.getClientToken(clientToken);
}
/**
* 获取:用户授权记录
* @param clientId 应用id
* @param loginId 账号id
* @return 权限
*/
public static String getGrantScope(String clientId, Object loginId) {
return saOAuth2Template.getGrantScope(clientId, loginId);
}
}

View File

@@ -1,32 +1,35 @@
package cn.dev33.satoken.oauth2.model;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Model: access_token
* Model: Access-Token
* @author kong
*
*/
public class AccessTokenModel {
public class AccessTokenModel implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/**
* access_token 值
* Access-Token 值
*/
public String accessToken;
/**
* refresh_token 值
* Refresh-Token 值
*/
public String refreshToken;
/**
* access_token 到期时间
* Access-Token 到期时间
*/
public long expiresTime;
/**
* refresh_token 到期时间
* Refresh-Token 到期时间
*/
public long refreshExpiresTime;
@@ -92,7 +95,6 @@ public class AccessTokenModel {
return s < 1 ? -2 : s;
}
/**
* 将所有属性转换为下划线形式的Map
* @return

View File

@@ -1,22 +1,25 @@
package cn.dev33.satoken.oauth2.model;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Model: client_token
* Model: Client-Token
* @author kong
*
*/
public class ClientTokenModel {
public class ClientTokenModel implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/**
* client_token 值
* Client-Token 值
*/
public String clientToken;
/**
* client_token 到期时间
* Client-Token 到期时间
*/
public long expiresTime;

View File

@@ -1,11 +1,15 @@
package cn.dev33.satoken.oauth2.model;
import java.io.Serializable;
/**
* Model: [授权码 - 数据 对应关系]
* Model: 授权码
* @author kong
*
*/
public class CodeModel {
public class CodeModel implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/**
* 授权码

View File

@@ -1,18 +1,23 @@
package cn.dev33.satoken.oauth2.model;
import java.io.Serializable;
/**
* Model: refresh_token
* Model: Refresh-Token
* @author kong
*
*/
public class RefreshTokenModel {
public class RefreshTokenModel implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/**
* refresh_token 值
* Refresh-Token 值
*/
public String refreshToken;
/**
* refresh_token到期时间
* Refresh-Token 到期时间
*/
public long expiresTime;

View File

@@ -1,5 +1,7 @@
package cn.dev33.satoken.oauth2.model;
import java.io.Serializable;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.util.SaFoxUtil;
@@ -8,7 +10,9 @@ import cn.dev33.satoken.util.SaFoxUtil;
* @author kong
*
*/
public class RequestAuthModel {
public class RequestAuthModel implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/**
* 应用id

View File

@@ -0,0 +1,115 @@
package cn.dev33.satoken.oauth2.model;
import java.io.Serializable;
/**
* Client应用信息 Model
* @author kong
*
*/
public class SaClientModel implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/**
* 应用id
*/
public String clientId;
/**
* 应用秘钥
*/
public String clientSecret;
/**
* 应用签约的所有权限, 多个用逗号隔开
*/
public String contractScope;
/**
* 应用允许授权的所有URL, 多个用逗号隔开
*/
public String allowUrl;
public SaClientModel() {
}
public SaClientModel(String clientId, String clientSecret, String contractScope, String allowUrl) {
super();
this.clientId = clientId;
this.clientSecret = clientSecret;
this.contractScope = contractScope;
this.allowUrl = allowUrl;
}
/**
* @return 应用id
*/
public String getClientId() {
return clientId;
}
/**
* @param clientId 应用id
* @return 对象自身
*/
public SaClientModel setClientId(String clientId) {
this.clientId = clientId;
return this;
}
/**
* @return 应用秘钥
*/
public String getClientSecret() {
return clientSecret;
}
/**
* @param clientSecret 应用秘钥
* @return 对象自身
*/
public SaClientModel setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
return this;
}
/**
* @return 应用签约的所有权限, 多个用逗号隔开
*/
public String getContractScope() {
return contractScope;
}
/**
* @param contractScope 应用签约的所有权限, 多个用逗号隔开
* @return 对象自身
*/
public SaClientModel setContractScope(String contractScope) {
this.contractScope = contractScope;
return this;
}
/**
* @return 应用允许授权的所有URL, 多个用逗号隔开
*/
public String getAllowUrl() {
return allowUrl;
}
/**
* @param allowUrl 应用允许授权的所有URL, 多个用逗号隔开
* @return 对象自身
*/
public SaClientModel setAllowUrl(String allowUrl) {
this.allowUrl = allowUrl;
return this;
}
@Override
public String toString() {
return "SaClientModel [clientId=" + clientId + ", clientSecret=" + clientSecret + ", contractScope="
+ contractScope + ", allowUrl=" + allowUrl + "]";
}
}