OAuth2.0模块 beta

This commit is contained in:
click33
2021-07-17 23:14:23 +08:00
parent 93e231ff18
commit 742b65366a
29 changed files with 1655 additions and 712 deletions

View File

@@ -1,5 +1,6 @@
package cn.dev33.satoken.context.model;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.util.SaFoxUtil;
/**
@@ -20,7 +21,7 @@ public interface SaRequest {
* @param name 键
* @return 值
*/
public String getParameter(String name);
public String getParam(String name);
/**
* 在 [请求体] 里获取一个值,值为空时返回默认值
@@ -28,14 +29,39 @@ public interface SaRequest {
* @param defaultValue 值为空时的默认值
* @return 值
*/
public default String getParameter(String name, String defaultValue) {
String value = getParameter(name);
public default String getParam(String name, String defaultValue) {
String value = getParam(name);
if(SaFoxUtil.isEmpty(value)) {
return defaultValue;
}
return value;
}
/**
* 检测提供的参数是否为指定值
* @param name 键
* @param value 值
* @return 是否相等
*/
public default boolean isParam(String name, String value) {
String paramValue = getParam(name);
return paramValue != null && paramValue.equals(value);
}
/**
* 在 [请求体] 里获取一个值 (此值必须存在,否则抛出异常
* @param name 键
* @return 参数值
*/
public default String getParamNotNull(String name) {
String paramValue = getParam(name);
if(SaFoxUtil.isEmpty(paramValue)) {
throw new SaTokenException("缺少参数:" + name);
}
return paramValue;
}
/**
* 在 [请求头] 里获取一个值
* @param name 键

View File

@@ -30,7 +30,7 @@ public interface SaTokenDao {
* 写入Value并设定存活时间 (单位: 秒)
* @param key 键名称
* @param value 值
* @param timeout 过期时间
* @param timeout 过期时间(值>0时限时存储值=-1时永久存储值=0或<=-2时不存储)
*/
public void set(String key, String value, long timeout);
@@ -75,7 +75,7 @@ public interface SaTokenDao {
* 写入Object并设定存活时间 (单位: 秒)
* @param key 键名称
* @param object 值
* @param timeout 存活时间
* @param timeout 存活时间 (值>0时限时存储值=-1时永久存储值=0或<=-2时不存储)
*/
public void setObject(String key, Object object, long timeout);

View File

@@ -45,6 +45,9 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
@Override
public void set(String key, String value, long timeout) {
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
return;
}
dataMap.put(key, value);
expireMap.put(key, (timeout == SaTokenDao.NEVER_EXPIRE) ? (SaTokenDao.NEVER_EXPIRE) : (System.currentTimeMillis() + timeout * 1000));
}
@@ -84,6 +87,9 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
@Override
public void setObject(String key, Object object, long timeout) {
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
return;
}
dataMap.put(key, object);
expireMap.put(key, (timeout == SaTokenDao.NEVER_EXPIRE) ? (SaTokenDao.NEVER_EXPIRE) : (System.currentTimeMillis() + timeout * 1000));
}

View File

@@ -39,19 +39,19 @@ public class SaSsoHandle {
return sso.notLoginView.get();
}
// 情况2在SSO认证中心已经登录开始构建授权重定向地址下放ticket
String redirectUrl = SaSsoUtil.buildRedirectUrl(stpLogic.getLoginId(), req.getParameter(ParamName.redirect));
String redirectUrl = SaSsoUtil.buildRedirectUrl(stpLogic.getLoginId(), req.getParam(ParamName.redirect));
return res.redirect(redirectUrl);
}
// ---------- SSO-Server端RestAPI 登录接口
if(match(Api.ssoDoLogin)) {
return sso.doLoginHandle.apply(req.getParameter("name"), req.getParameter("pwd"));
return sso.doLoginHandle.apply(req.getParam("name"), req.getParam("pwd"));
}
// ---------- SSO-Server端校验ticket 获取账号id
if(match(Api.ssoCheckTicket) && sso.isHttp) {
String ticket = req.getParameter(ParamName.ticket);
String sloCallback = req.getParameter(ParamName.ssoLogoutCall);
String ticket = req.getParam(ParamName.ticket);
String sloCallback = req.getParam(ParamName.ssoLogoutCall);
// 校验ticket获取对应的账号id
Object loginId = SaSsoUtil.checkTicket(ticket);
@@ -65,8 +65,8 @@ public class SaSsoHandle {
// ---------- SSO-Server端单点注销
if(match(Api.ssoLogout) && sso.isSlo) {
String loginId = req.getParameter(ParamName.loginId);
String secretkey = req.getParameter(ParamName.secretkey);
String loginId = req.getParam(ParamName.loginId);
String secretkey = req.getParam(ParamName.secretkey);
// 遍历通知Client端注销会话
SaSsoUtil.singleLogout(secretkey, loginId, url -> sso.sendHttp.apply(url));
@@ -93,8 +93,8 @@ public class SaSsoHandle {
// ---------- SSO-Client端登录地址
if(match(Api.ssoLogin)) {
String back = req.getParameter(ParamName.back, "/");
String ticket = req.getParameter(ParamName.ticket);
String back = req.getParam(ParamName.back, "/");
String ticket = req.getParam(ParamName.ticket);
// 如果当前Client端已经登录则无需访问SSO认证中心可以直接返回
if(stpLogic.isLogin()) {
@@ -138,10 +138,10 @@ public class SaSsoHandle {
// ---------- SSO-Client端单点注销 [模式二]
if(match(Api.ssoLogout) && sso.isSlo && sso.isHttp == false) {
stpLogic.logout();
if(req.getParameter(ParamName.back) == null) {
if(req.getParam(ParamName.back) == null) {
return SaResult.ok("单点注销成功");
} else {
return res.redirect(req.getParameter(ParamName.back, "/"));
return res.redirect(req.getParam(ParamName.back, "/"));
}
}
@@ -155,10 +155,10 @@ public class SaSsoHandle {
String url = SaSsoUtil.buildSloUrl(stpLogic.getLoginId());
String body = String.valueOf(sso.sendHttp.apply(url));
if(SaSsoConsts.OK.equals(body)) {
if(req.getParameter(ParamName.back) == null) {
if(req.getParam(ParamName.back) == null) {
return SaResult.ok("单点注销成功");
} else {
return res.redirect(req.getParameter(ParamName.back, "/"));
return res.redirect(req.getParam(ParamName.back, "/"));
}
}
return SaResult.error("单点注销失败");
@@ -166,8 +166,8 @@ public class SaSsoHandle {
// ---------- SSO-Client端单点注销的回调 [模式三]
if(match(Api.ssoLogoutCall) && sso.isSlo && sso.isHttp) {
String loginId = req.getParameter(ParamName.loginId);
String secretkey = req.getParameter(ParamName.secretkey);
String loginId = req.getParam(ParamName.loginId);
String secretkey = req.getParam(ParamName.secretkey);
SaSsoUtil.checkSecretkey(secretkey);
stpLogic.logoutByTokenValue(stpLogic.getTokenValueByLoginId(loginId));

View File

@@ -132,7 +132,7 @@ public class StpLogic {
}
// 2. 尝试从请求体里面读取
if(tokenValue == null && config.getIsReadBody()){
tokenValue = request.getParameter(keyTokenName);
tokenValue = request.getParam(keyTokenName);
}
// 3. 尝试从header里读取
if(tokenValue == null && config.getIsReadHead()){

View File

@@ -204,7 +204,7 @@ public class SaFoxUtil {
if(url == null) {
url = "";
}
int index = url.indexOf('?');
int index = url.lastIndexOf('?');
// ? 不存在
if(index == -1) {
return url + '?' + parameStr;
@@ -236,12 +236,64 @@ public class SaFoxUtil {
*/
public static String joinParam(String url, String key, Object value) {
// 如果参数为空, 直接返回
if(isEmpty(url) || isEmpty(key) || isEmpty(String.valueOf(value))) {
if(isEmpty(url) || isEmpty(key) || isEmpty(value)) {
return url;
}
return joinParam(url, key + "=" + value);
}
/**
* 在url上拼接锚参数
* @param url url
* @param parameStr 参数, 例如 id=1001
* @return 拼接后的url字符串
*/
public static String joinSharpParam(String url, String parameStr) {
// 如果参数为空, 直接返回
if(parameStr == null || parameStr.length() == 0) {
return url;
}
if(url == null) {
url = "";
}
int index = url.lastIndexOf('#');
// ? 不存在
if(index == -1) {
return url + '#' + parameStr;
}
// ? 是最后一位
if(index == url.length() - 1) {
return url + parameStr;
}
// ? 是其中一位
if(index > -1 && index < url.length() - 1) {
String separatorChar = "&";
// 如果最后一位是 不是&, 且 parameStr 第一位不是 &, 就增送一个 &
if(url.lastIndexOf(separatorChar) != url.length() - 1 && parameStr.indexOf(separatorChar) != 0) {
return url + separatorChar + parameStr;
} else {
return url + parameStr;
}
}
// 正常情况下, 代码不可能执行到此
return url;
}
/**
* 在url上拼接锚参数
* @param url url
* @param key 参数名称
* @param value 参数值
* @return 拼接后的url字符串
*/
public static String joinSharpParam(String url, String key, Object value) {
// 如果参数为空, 直接返回
if(isEmpty(url) || isEmpty(key) || isEmpty(value)) {
return url;
}
return joinSharpParam(url, key + "=" + value);
}
/**
* 将数组的所有元素使用逗号拼接在一起
* @param arr 数组

View File

@@ -43,7 +43,7 @@
</dependency>
<!-- sa-token整合redis (使用jackson序列化方式) -->
<!-- <dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>${sa-token-version}</version>
@@ -51,7 +51,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency> -->
</dependency>
<!-- ConfigurationProperties -->
<dependency>

View File

@@ -12,7 +12,7 @@ public class SaOAuth2ServerApplication {
public static void main(String[] args) {
SpringApplication.run(SaOAuth2ServerApplication.class, args);
System.out.println("\n服务端启动成功");
System.out.println("\nOAuth-Server端启动成功");
}
}

View File

@@ -7,22 +7,186 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.pj.utils.AjaxJson;
import com.pj.utils.SoMap;
import cn.dev33.satoken.context.SaHolder;
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.SaOAuth2Handle;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Util;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Param;
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.spring.SpringMVCUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
@RestController
@RequestMapping("/oauth2/")
//@RequestMapping("/oauth2/")
public class OAuth2Controller {
// OAuth-Server端处理所有OAuth相关请求
@RequestMapping("/oauth2/authorize")
public Object request() {
System.out.println("------------进入请求:" + SaHolder.getRequest().getUrl());
return SaOAuth2Handle.authorize();
}
// OAuth-Server端处理所有OAuth相关请求
@RequestMapping("/oauth2/token")
public Object token() {
System.out.println("------------进入请求:" + SaHolder.getRequest().getUrl());
return SaOAuth2Handle.token();
}
// OAuth-Server端刷新Token
@RequestMapping("/oauth2/ref")
public Object ref(String refresh_token) {
System.out.println("------------进入请求:" + SaHolder.getRequest().getUrl());
return SaResult.data(
SaOAuth2Util.saOAuth2Template.refreshAccessToken(refresh_token).toLineMap()
);
}
// 隐藏式
@RequestMapping("/oauth2/yc")
public Object yc() {
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// ------------- 以下都是雷同代码
// 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);
}
// ------------- 以上都是雷同代码
// 6、开始重定向授权下放code
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra);
String redirectUri = SaOAuth2Util.buildRedirectUri2(ra.redirectUri, at.accessToken, ra.state);
return res.redirect(redirectUri);
}
// 密码式
@RequestMapping("/oauth2/password")
public Object password() {
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// 1、构建请求Model TODO 貌似这个RequestAuthModel对象也可以省略掉
// RequestAuthModel ra = SaOAuth2Util.generateRequestAuth(req, StpUtil.getLoginId());
String username = req.getParamNotNull("username");
String password = req.getParamNotNull("password");
String clientId = req.getParamNotNull("client_id");
Object retObj = cfg.doLoginHandle.apply(username, password);
if(StpUtil.isLogin() == false) {
return retObj;
}
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);
ra.scope = "";// 默认应该为空还是内个呢 SaOAuth2Util.saOAuth2Template.getClientScopeList(clientId);
ra.loginId = StpUtil.getLoginId();
// 6、开始重定向授权下放code TODO 这里需要也生成 ref_token
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra);
//
return SaResult.data(at);
}
// 凭证式
@RequestMapping("/oauth2/appat")
public Object appat() {
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
String clientId = req.getParamNotNull(Param.client_id);
String scope = req.getParam(Param.scope);
ClientTokenModel ct = SaOAuth2Util.generateClientToken(clientId, scope);
//
return SaResult.data(ct.toLineMap());
}
@Autowired
public void setSaOAuth2Config(SaOAuth2Config saOAuth2Config) {
System.out.println("-----------123 " + saOAuth2Config);
saOAuth2Config.
// 未登录的视图
setNotLoginView(()->{
// return "您暂未登录";
HttpServletRequest request = SpringMVCUtil.getRequest();
HttpServletResponse response = SpringMVCUtil.getResponse();
response.setContentType("text/html");
try {
request.getRequestDispatcher("/login.html").forward(request, response);
} catch (ServletException | IOException e) {
e.printStackTrace();
}
return null;
}).
// 未登录的视图
setConfirmView((clientId, scope)->{
return "本次操作需要授权";
})
// 登录处理函数
.setDoLoginHandle((name, pwd) -> {
if("sa".equals(name) && "123456".equals(pwd)) {
StpUtil.login(10001);
return AjaxJson.getSuccess();
}
return SaResult.error();
})
;
}
// 获取授权码
@RequestMapping("/authorize")
@@ -53,17 +217,17 @@ public class OAuth2Controller {
// 打印调试
System.out.println("应用id=" + authModel.getClientId() + "请求授权,授权类型=" + authModel.getResponseType());
System.out.println("重定向地址:" + authModel.getRedirectUri());
System.out.println("拼接完成的redirect_uri: " + codeModel.getRedirectUri());
System.out.println("如果用户拒绝授权,则重定向至: " + codeModel.getRejectUri());
// System.out.println("拼接完成的redirect_uri: " + codeModel.getRedirectUri());
// System.out.println("如果用户拒绝授权,则重定向至: " + codeModel.getRejectUri());
// 如果请求的权限用户已经确认,直接开始重定向授权
if(codeModel.getIsConfirm() == true) {
response.sendRedirect(codeModel.getRedirectUri());
} else {
// 如果请求的权限用户尚未确认,则进入到确定页
request.setAttribute("name", "sdd");
response.sendRedirect("/auth.html?code=" + codeModel.getCode());
}
// if(codeModel.getIsConfirm() == true) {
// response.sendRedirect(codeModel.getRedirectUri());
// } else {
// // 如果请求的权限用户尚未确认,则进入到确定页
// request.setAttribute("name", "sdd");
// response.sendRedirect("/auth.html?code=" + codeModel.getCode());
// }
return AjaxJson.getSuccess();
}
@@ -92,7 +256,7 @@ public class OAuth2Controller {
return AjaxJson.getError("暂无权限");
}
// 进行确认
SaOAuth2Util.confirmCode(code);
// SaOAuth2Util.confirmCode(code);
// 返回ok
return AjaxJson.getSuccess();
@@ -108,11 +272,11 @@ public class OAuth2Controller {
String clientSecret = request.getParameter("client_secret"); // 应用秘钥
// 校验参数
SaOAuth2Util.checkCodeIdSecret(code, clientId, clientSecret);
// SaOAuth2Util.checkCodeIdSecret(code, clientId, clientSecret);
// 生成
CodeModel codeModel = SaOAuth2Util.getCode(code);
AccessTokenModel tokenModel = SaOAuth2Util.generateAccessToken(codeModel);
AccessTokenModel tokenModel = SaOAuth2Util.generateAccessToken(code);
// 生成AccessToken之后将授权码立即销毁
SaOAuth2Util.deleteCode(code);

View File

@@ -0,0 +1,29 @@
package com.pj.oauth2;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
/**
* 注册Bean
*
* @author kong
*
*/
@Component
public class SaOAuth2BeanRegister {
/**
* 获取OAuth2配置Bean
*
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token.oauth2")
public SaOAuth2Config getSaOAuth2Config() {
return new SaOAuth2Config();
}
}

View File

@@ -1,8 +1,6 @@
package com.pj.oauth2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
@@ -19,17 +17,6 @@ import cn.dev33.satoken.oauth2.logic.SaOAuth2Util;
@Component
public class SaOAuth2SpringAutowired {
/**
* 获取OAuth2配置Bean
*
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token.oauth2")
public SaOAuth2Config getSaOAuth2Config() {
return new SaOAuth2Config();
}
/**
* 注入OAuth2配置Bean
*
@@ -50,5 +37,4 @@ public class SaOAuth2SpringAutowired {
SaOAuth2Util.saOAuth2Template = saOAuth2Interface;
}
}

View File

@@ -99,6 +99,9 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
*/
@Override
public void set(String key, String value, long timeout) {
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
return;
}
// 判断是否为永不过期
if(timeout == SaTokenDao.NEVER_EXPIRE) {
stringRedisTemplate.opsForValue().set(key, value);
@@ -170,6 +173,9 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
*/
@Override
public void setObject(String key, Object object, long timeout) {
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
return;
}
// 判断是否为永不过期
if(timeout == SaTokenDao.NEVER_EXPIRE) {
objectRedisTemplate.opsForValue().set(key, object);

View File

@@ -79,6 +79,9 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public void set(String key, String value, long timeout) {
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
return;
}
// 判断是否为永不过期
if(timeout == SaTokenDao.NEVER_EXPIRE) {
stringRedisTemplate.opsForValue().set(key, value);
@@ -149,6 +152,9 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public void setObject(String key, Object object, long timeout) {
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
return;
}
// 判断是否为永不过期
if(timeout == SaTokenDao.NEVER_EXPIRE) {
objectRedisTemplate.opsForValue().set(key, object);

View File

@@ -1,5 +1,12 @@
package cn.dev33.satoken.oauth2.config;
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
* @author kong
@@ -22,6 +29,11 @@ public class SaOAuth2Config {
*/
private long refreshTokenTimeout = 60 * 60 * 24 * 30;
/**
* client_token默认保存的时间(单位秒) 默认两个小时
*/
private long clientTokenTimeout = 60 * 60 * 2;
/**
* @return codeTimeout
@@ -71,9 +83,121 @@ public class SaOAuth2Config {
return this;
}
/**
* @return clientTokenTimeout
*/
public long getClientTokenTimeout() {
return clientTokenTimeout;
}
/**
* @param clientTokenTimeout 要设置的 clientTokenTimeout
* @return 对象自身
*/
public SaOAuth2Config setClientTokenTimeout(long clientTokenTimeout) {
this.clientTokenTimeout = clientTokenTimeout;
return this;
}
// -------------------- 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
*/
public BiFunction<String, String, Object> confirmView = (clientId, scope) -> "本次操作需要用户授权";
/**
* OAuth-Server端登录函数
*/
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 对象自身
*/
public SaOAuth2Config setNotLoginView(Supplier<Object> notLoginView) {
this.notLoginView = notLoginView;
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 对象自身
*/
public SaOAuth2Config setConfirmView(BiFunction<String, String, Object> confirmView) {
this.confirmView = confirmView;
return this;
}
/**
* @param doLoginHandle OAuth-Server端登录函数
* @return 对象自身
*/
public SaOAuth2Config setDoLoginHandle(BiFunction<String, String, Object> doLoginHandle) {
this.doLoginHandle = doLoginHandle;
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 + "]";
}
}

View File

@@ -0,0 +1,35 @@
package cn.dev33.satoken.oauth2.exception;
import cn.dev33.satoken.exception.SaTokenException;
/**
* 一个异常代表OAuth2认证流程错误
*
* @author kong
*/
public class SaOAuth2Exception extends SaTokenException {
/**
* 序列化版本号
*/
private static final long serialVersionUID = 6806129545290130114L;
/**
* 一个异常代表OAuth2认证流程错误
*/
public SaOAuth2Exception(String message) {
super(message);
}
/**
* 如果flag==true则抛出message异常
* @param flag 标记
* @param message 异常信息
*/
public static void throwBy(boolean flag, String message) {
if(flag) {
throw new SaOAuth2Exception(message);
}
}
}

View File

@@ -0,0 +1,92 @@
package cn.dev33.satoken.oauth2.logic;
/**
* Sa-Token-OAuth2 所有常量
* @author kong
*
*/
public class SaOAuth2Consts {
/**
* 所有API接口
* @author kong
*/
public static final class Api {
/** OAuth-Server端授权地址 */
public static String authorize = "/oauth2/authorize";
}
/**
* 所有参数名称
* @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 grant_type = "grant_type";
}
/**
* 所有授权类型
*/
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 String authorization_code = "authorization_code";
}
/**
* 在保存授权码时用到的key
*/
public static final String UNLIMITED_DOMAIN = "*";
/** 表示OK的返回结果 */
public static final String OK = "ok";
/** 表示请求没有得到任何有效处理 */
public static final String NOT_HANDLE = "not handle";
}

View File

@@ -0,0 +1,125 @@
package cn.dev33.satoken.oauth2.logic;
import cn.dev33.satoken.context.SaHolder;
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.logic.SaOAuth2Consts.Param;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
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;
/**
* Sa-Token-OAuth2 请求处理类封装
* @author kong
*
*/
public class SaOAuth2Handle {
/**
* 处理Server端请求
* @return 处理结果
*/
public static Object authorize() {
// 获取变量
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);
}
// 6、开始重定向授权下放code
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());
}
// 默认返回
return SaOAuth2Consts.NOT_HANDLE;
}
/**
* 路由匹配算法
* @param pattern 路由表达式
* @return 是否可以匹配
*/
static boolean match(String pattern) {
return SaRouter.isMatch(pattern, SaHolder.getRequest().getRequestPath());
}
}

View File

@@ -2,8 +2,11 @@ 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;
/**
@@ -15,6 +18,27 @@ 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);
}
// ---------------------------------------------- 分界线 -----------------------------------------------------
// ------------------- 获取数据
@@ -48,6 +72,15 @@ public class SaOAuth2Util {
// ------------------- 数据校验
/**
* [OK] 判断该Client是否签约了指定的Scope
* @param clientId 应用id
* @param scope 权限
*/
public static boolean isContract(String clientId, String scope) {
return saOAuth2Template.isContract(clientId, scope);
}
/**
* 指定 loginId 是否对一个 Client 授权给了指定 Scope
* @param clientId 应用id
@@ -60,14 +93,25 @@ public class SaOAuth2Util {
}
/**
* 校验code、clientId、clientSecret 三者是否正确
* [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) {
return saOAuth2Template.checkCodeIdSecret(code, clientId, clientSecret);
public static CodeModel checkCodeIdSecret(String code, String clientId, String clientSecret, String redirectUri) {
return saOAuth2Template.checkCodeIdSecret(code, clientId, clientSecret, redirectUri);
}
/**
@@ -86,7 +130,7 @@ public class SaOAuth2Util {
// ------------------- 逻辑相关
/**
* 根据参数生成一个授权码并返回
* [OK] 根据参数生成一个授权码并返回
* @param authModel 请求授权参数Model
* @return 授权码Model
*/
@@ -94,6 +138,7 @@ public class SaOAuth2Util {
return saOAuth2Template.generateCode(authModel);
}
/**
* 根据授权码获得授权码Model
* @param code 授权码
@@ -103,23 +148,6 @@ public class SaOAuth2Util {
return saOAuth2Template.getCode(code);
}
/**
* 手动更改授权码对象信息
* @param code 授权码
* @param codeModel 授权码Model
*/
public static void updateCode(String code, CodeModel codeModel) {
saOAuth2Template.updateCode(code, codeModel);
}
/**
* 确认授权一个code
* @param code 授权码
*/
public static void confirmCode(String code) {
saOAuth2Template.confirmCode(code);
}
/**
* [default] 删除一个授权码
* @param code 授权码
@@ -129,12 +157,12 @@ public class SaOAuth2Util {
}
/**
* [default] 根据授权码Model生成一个access_token
* 根据授权码Model生成一个access_token
* @param codeModel 授权码Model
* @return AccessTokenModel
*/
public static AccessTokenModel generateAccessToken(CodeModel codeModel) {
return saOAuth2Template.generateAccessToken(codeModel);
public static AccessTokenModel generateAccessToken(String code) {
return saOAuth2Template.generateAccessToken(code);
}
/**
@@ -156,32 +184,14 @@ public class SaOAuth2Util {
}
/**
* [default] 根据 refresh_token 获得其Model详细信息 (授权码Model)
* [default] 根据 refresh_token 获得其Model详细信息
* @param refreshToken refresh_token
* @return RefreshToken (授权码Model)
* @return RefreshToken
*/
public static CodeModel getRefreshToken(String refreshToken) {
public static RefreshTokenModel getRefreshToken(String refreshToken) {
return saOAuth2Template.getRefreshToken(refreshToken);
}
/**
* [default] 获取 access_token 的有效期
* @param accessToken access_token
* @return 有效期
*/
public static long getAccessTokenExpiresIn(String accessToken) {
return saOAuth2Template.getAccessTokenExpiresIn(accessToken);
}
/**
* [default] 获取 refresh_token 的有效期
* @param refreshToken refresh_token
* @return 有效期
*/
public static long getRefreshTokenExpiresIn(String refreshToken) {
return saOAuth2Template.getRefreshTokenExpiresIn(refreshToken);
}
/**
* [default] 获取 access_token 所代表的LoginId
* @param accessToken access_token
@@ -191,10 +201,46 @@ public class SaOAuth2Util {
return saOAuth2Template.getLoginIdByAccessToken(accessToken);
}
/**
* 构建AccessToken Model (根据RequestAuthModel) 用于隐藏式
* @param ra 请求授权参数Model
* @return 授权码Model
*/
public static AccessTokenModel generateAccessToken(RequestAuthModel ra) {
return saOAuth2Template.generateAccessToken(ra);
}
/**
* 构建ClientToken Model
* @param ra 请求授权参数Model
* @return ClientToken-Model
*/
public static ClientTokenModel generateClientToken(String clientId, String scope) {
return saOAuth2Template.generateClientToken(clientId, scope);
}
// ------------------- 自定义策略相关
/**
* [OK] 构建URL下放授权码URL
* @param redirectUri 下放地址
* @param code code参数
* @param state state参数
* @return 构建完毕的URL
*/
public static String buildRedirectUri(String redirectUri, String code, String state) {
return saOAuth2Template.buildRedirectUri(redirectUri, code, state);
}
/**
* [OK] 构建URL下放Token URL
* @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);
}
}

View File

@@ -1,5 +1,8 @@
package cn.dev33.satoken.oauth2.model;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Model: access_token
* @author kong
@@ -10,177 +13,100 @@ public class AccessTokenModel {
/**
* access_token 值
*/
private String accessToken;
public String accessToken;
/**
* refresh_token 值
*/
private String refreshToken;
public String refreshToken;
/**
* access_token 剩余有效时间 (秒)
* access_token 到期时间
*/
private long expiresIn;
public long expiresTime;
/**
* refresh_token 剩余有效期 (秒)
* refresh_token 到期时间
*/
private long refreshExpiresIn;
/**
* 此 access_token令牌 是由哪个code码创建
*/
private String code;
public long refreshExpiresTime;
/**
* 应用id
*/
private String clientId;
public String clientId;
/**
* 授权范围
* 账号id
*/
private String scope;
public Object loginId;
/**
* 开放账号id
*/
private String openid;
public String openid;
/**
* 其他自定义数据
* 授权范围
*/
private Object tag;
public String scope;
public AccessTokenModel() {}
/**
* @return accessToken
* 构建一个
* @param accessToken accessToken
* @param clientId 应用id
* @param scope 请求授权范围
* @param loginId 对应的账号id
*/
public String getAccessToken() {
return accessToken;
}
/**
* @param accessToken 要设置的 accessToken
*/
public void setAccessToken(String accessToken) {
public AccessTokenModel(String accessToken, String clientId, Object loginId, String scope) {
super();
this.accessToken = accessToken;
}
/**
* @return refreshToken
*/
public String getRefreshToken() {
return refreshToken;
}
/**
* @param refreshToken 要设置的 refreshToken
*/
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
/**
* @return expiresIn
*/
public long getExpiresIn() {
return expiresIn;
}
/**
* @param expiresIn 要设置的 expiresIn
*/
public void setExpiresIn(long expiresIn) {
this.expiresIn = expiresIn;
}
/**
* @return refreshExpiresIn
*/
public long getRefreshExpiresIn() {
return refreshExpiresIn;
}
/**
* @param refreshExpiresIn 要设置的 refreshExpiresIn
*/
public void setRefreshExpiresIn(long refreshExpiresIn) {
this.refreshExpiresIn = refreshExpiresIn;
}
/**
* @return code
*/
public String getCode() {
return code;
}
/**
* @param code 要设置的 code
*/
public void setCode(String code) {
this.code = code;
}
/**
* @return clientId
*/
public String getClientId() {
return clientId;
}
/**
* @param clientId 要设置的 clientId
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return scope
*/
public String getScope() {
return scope;
}
/**
* @param scope 要设置的 scope
*/
public void setScope(String scope) {
this.loginId = loginId;
this.scope = scope;
}
@Override
public String toString() {
return "AccessTokenModel [accessToken=" + accessToken + ", refreshToken=" + refreshToken
+ ", accessTokenTimeout=" + expiresTime + ", refreshTokenTimeout=" + refreshExpiresTime
+ ", clientId=" + clientId + ", scope=" + scope + ", openid=" + openid + "]";
}
/**
* @return openid
* 获取:此 Access-Token 的剩余有效期(秒)
* @return see note
*/
public String getOpenid() {
return openid;
public long getExpiresIn() {
long s = (expiresTime - System.currentTimeMillis()) / 1000;
return s < 1 ? -2 : s;
}
/**
* @param openid 要设置的 openid
* 获取:此 Refresh-Token 的剩余有效期(秒)
* @return see note
*/
public void setOpenid(String openid) {
this.openid = openid;
public long getRefreshExpiresIn() {
long s = (refreshExpiresTime - System.currentTimeMillis()) / 1000;
return s < 1 ? -2 : s;
}
/**
* @return tag
* 将所有属性转换为下划线形式的Map
* @return
*/
public Object getTag() {
return tag;
public Map<String, Object> toLineMap() {
Map<String, Object> map = new LinkedHashMap<String, Object>();
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("scope", scope);
map.put("openid", openid);
return map;
}
/**
* @param tag 要设置的 tag
*/
public void setTag(Object tag) {
this.tag = tag;
}
}

View File

@@ -0,0 +1,78 @@
package cn.dev33.satoken.oauth2.model;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Model: client_token
* @author kong
*
*/
public class ClientTokenModel {
/**
* client_token 值
*/
public String clientToken;
/**
* client_token 到期时间
*/
public long expiresTime;
/**
* 应用id
*/
public String clientId;
/**
* 授权范围
*/
public String scope;
public ClientTokenModel() {}
/**
* 构建一个
* @param accessToken accessToken
* @param clientId 应用id
* @param scope 请求授权范围
* @param loginId 对应的账号id
*/
public ClientTokenModel(String accessToken, String clientId, String scope) {
super();
this.clientToken = accessToken;
this.clientId = clientId;
this.scope = scope;
}
@Override
public String toString() {
return "ClientTokenModel [clientToken=" + clientToken + ", expiresTime=" + expiresTime + ", clientId="
+ clientId + ", scope=" + scope + "]";
}
/**
* 获取:此 Client-Token 的剩余有效期(秒)
* @return see note
*/
public long getExpiresIn() {
long s = (expiresTime - System.currentTimeMillis()) / 1000;
return s < 1 ? -2 : s;
}
/**
* 将所有属性转换为下划线形式的Map
* @return
*/
public Map<String, Object> toLineMap() {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("client_token", clientToken);
map.put("expires_in", getExpiresIn());
map.put("client_id", clientId);
map.put("scope", scope);
return map;
}
}

View File

@@ -10,44 +10,27 @@ public class CodeModel {
/**
* 授权码
*/
private String code;
public String code;
/**
* 应用id
*/
private String clientId;
public String clientId;
/**
* 授权范围
*/
private String scope;
public String scope;
/**
* 对应账号id
*/
private Object loginId;
public Object loginId;
/**
* 用户是否已经确认了这个授权
* 重定向的地址
*/
private Boolean isConfirm;
/**
* 确认授权后重定向的地址
*/
private String redirectUri;
/**
* 拒绝授权后重定向的地址
*/
private String rejectUri;
/**
* 其他自定义数据
*/
private Object tag;
public String redirectUri;
/**
* 构建一个
@@ -62,17 +45,16 @@ public class CodeModel {
* @param scope 请求授权范围
* @param loginId 对应的账号id
*/
public CodeModel(String code, String clientId, String scope, Object loginId) {
public CodeModel(String code, String clientId, String scope, Object loginId, String redirectUri) {
super();
this.code = code;
this.clientId = clientId;
this.scope = scope;
this.loginId = loginId;
this.isConfirm = false;
this.redirectUri = redirectUri;
}
/**
* @return code
*/
@@ -129,20 +111,6 @@ public class CodeModel {
this.loginId = loginId;
}
/**
* @return isConfirm
*/
public Boolean getIsConfirm() {
return isConfirm;
}
/**
* @param isConfirm 要设置的 isConfirm
*/
public void setIsConfirm(Boolean isConfirm) {
this.isConfirm = isConfirm;
}
/**
* @return redirectUri
*/
@@ -157,35 +125,10 @@ public class CodeModel {
this.redirectUri = redirectUri;
}
/**
* @return rejectUri
*/
public String getRejectUri() {
return rejectUri;
}
/**
* @param rejectUri 要设置的 rejectUri
*/
public void setRejectUri(String rejectUri) {
this.rejectUri = rejectUri;
@Override
public String toString() {
return "CodeModel [code=" + code + ", clientId=" + clientId + ", scope=" + scope + ", loginId=" + loginId
+ ", redirectUri=" + redirectUri + "]";
}
/**
* @return tag
*/
public Object getTag() {
return tag;
}
/**
* @param tag 要设置的 tag
*/
public void setTag(Object tag) {
this.tag = tag;
}
}

View File

@@ -0,0 +1,54 @@
package cn.dev33.satoken.oauth2.model;
/**
* Model: refresh_token
* @author kong
*
*/
public class RefreshTokenModel {
/**
* refresh_token 值
*/
public String refreshToken;
/**
* refresh_token到期时间
*/
public long expiresTime;
/**
* 应用id
*/
public String clientId;
/**
* 授权范围
*/
public String scope;
/**
* 对应账号id
*/
public Object loginId;
/**
* 对应账号id
*/
public String openid;
@Override
public String toString() {
return "RefreshTokenModel [refreshToken=" + refreshToken + ", expiresTime=" + expiresTime
+ ", clientId=" + clientId + ", scope=" + scope + ", loginId=" + loginId + ", openid=" + openid + "]";
}
/**
* 获取:此 Refresh-Token 的剩余有效期(秒)
* @return see note
*/
public long getExpiresIn() {
long s = (expiresTime - System.currentTimeMillis()) / 1000;
return s < 1 ? -2 : s;
}
}

View File

@@ -13,32 +13,32 @@ public class RequestAuthModel {
/**
* 应用id
*/
private String clientId;
public String clientId;
/**
* 授权范围
*/
private String scope;
public String scope;
/**
* 对应的账号id
*/
private Object loginId;
public Object loginId;
/**
* 待重定向URL
*/
private String redirectUri;
public String redirectUri;
/**
* 授权类型, 非必填
*/
private String responseType;
public String responseType;
/**
* 状态标识, 可为null
*/
private String state;
public String state;
/**
@@ -157,4 +157,5 @@ public class RequestAuthModel {
return this;
}
}

View File

@@ -1,73 +1,73 @@
package cn.dev33.satoken.oauth2.model;
/**
* 权限Model
* @author kong
*
*/
public class ScopeModel {
/**
* 权限名称
*/
private String name;
/**
* 详细介绍
*/
private String introduce;
/**
* 构造一个
*/
public ScopeModel() {
super();
}
/**
* 构造一个
* @param name 权限名称
* @param introduce 权限详细介绍
*/
public ScopeModel(String name, String introduce) {
super();
this.name = name;
this.introduce = introduce;
}
/**
* @return name
*/
public String getName() {
return name;
}
/**
* @param name 要设置的 name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return introduce
*/
public String getIntroduce() {
return introduce;
}
/**
* @param introduce 要设置的 introduce
*/
public void setIntroduce(String introduce) {
this.introduce = introduce;
}
}
//package cn.dev33.satoken.oauth2.model;
//
///**
// * 权限Model
// * @author kong
// *
// */
//public class ScopeModel {
//
// /**
// * 权限名称
// */
// private String name;
//
// /**
// * 详细介绍
// */
// private String introduce;
//
//
// /**
// * 构造一个
// */
// public ScopeModel() {
// super();
// }
// /**
// * 构造一个
// * @param name 权限名称
// * @param introduce 权限详细介绍
// */
// public ScopeModel(String name, String introduce) {
// super();
// this.name = name;
// this.introduce = introduce;
// }
//
// /**
// * @return name
// */
// public String getName() {
// return name;
// }
//
// /**
// * @param name 要设置的 name
// */
// public void setName(String name) {
// this.name = name;
// }
//
// /**
// * @return introduce
// */
// public String getIntroduce() {
// return introduce;
// }
//
// /**
// * @param introduce 要设置的 introduce
// */
// public void setIntroduce(String introduce) {
// this.introduce = introduce;
// }
//
//
//
//
//
//
//
//
//}

View File

@@ -1,15 +0,0 @@
package cn.dev33.satoken.oauth2.util;
/**
* sa-token oauth2 模块 用到的所有常量
* @author kong
*
*/
public class SaOAuth2Consts {
/**
* 在保存授权码时用到的key
*/
public static final String UNLIMITED_DOMAIN = "*";
}

View File

@@ -38,7 +38,7 @@ public class SaRequestForReactor implements SaRequest {
* 在 [请求体] 里获取一个值
*/
@Override
public String getParameter(String name) {
public String getParam(String name) {
return request.getQueryParams().getFirst(name);
}

View File

@@ -37,7 +37,7 @@ public class SaRequestForServlet implements SaRequest {
* 在 [请求体] 里获取一个值
*/
@Override
public String getParameter(String name) {
public String getParam(String name) {
return request.getParameter(name);
}

View File

@@ -21,7 +21,7 @@ public class SaRequestForSolon implements SaRequest {
}
@Override
public String getParameter(String s) {
public String getParam(String s) {
return ctx.param(s);
}