This commit is contained in:
noear 2024-09-22 21:02:58 +08:00
commit d75e4b799d
8 changed files with 87 additions and 6 deletions

View File

@ -27,7 +27,7 @@ public SaResult userinfo() {
System.out.println("-------- 此Access-Token对应的账号id: " + loginId); System.out.println("-------- 此Access-Token对应的账号id: " + loginId);
// 校验 Access-Token 是否具有权限: userinfo // 校验 Access-Token 是否具有权限: userinfo
SaOAuth2Util.checkScope(accessToken, "userinfo"); SaOAuth2Util.checkAccessTokenScope(accessToken, "userinfo");
// 模拟账号信息 (真实环境需要查询数据库获取信息) // 模拟账号信息 (真实环境需要查询数据库获取信息)
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();

View File

@ -60,6 +60,7 @@ public class SaOAuth2Consts {
public static String pwd = "pwd"; public static String pwd = "pwd";
public static String build_redirect_uri = "build_redirect_uri"; public static String build_redirect_uri = "build_redirect_uri";
public static String Authorization = "Authorization"; public static String Authorization = "Authorization";
public static String nonce = "nonce";
} }
/** /**

View File

@ -170,6 +170,17 @@ public interface SaOAuth2Dao {
} }
} }
/**
* 持久化nonce-索引
* @param c .
*/
default void saveCodeNonceIndex(CodeModel c) {
if(c == null || SaFoxUtil.isEmpty(c.nonce)) {
return;
}
getSaTokenDao().set(splicingCodeNonceIndexSaveKey(c.code), c.nonce, SaOAuth2Manager.getServerConfig().getCodeTimeout());
}
// ------------------- delete数据 // ------------------- delete数据
@ -404,6 +415,18 @@ public interface SaOAuth2Dao {
return getSaTokenDao().get(splicingStateSaveKey(state)); return getSaTokenDao().get(splicingStateSaveKey(state));
} }
/**
* 获取nonce
* @param code /
* @return /
*/
default String getNonce(String code) {
if(SaFoxUtil.isEmpty(code)) {
return null;
}
return getSaTokenDao().get(splicingCodeNonceIndexSaveKey(code));
}
// ------------------- 拼接key // ------------------- 拼接key
@ -510,6 +533,15 @@ public interface SaOAuth2Dao {
return getSaTokenConfig().getTokenName() + ":oauth2:state:" + state; return getSaTokenConfig().getTokenName() + ":oauth2:state:" + state;
} }
/**
* 拼接keycode-nonce 索引 参数持久化
* @param code 授权码
* @return key
*/
default String splicingCodeNonceIndexSaveKey(String code) {
return getSaTokenConfig().getTokenName() + ":oauth2:code-nonce-index:" + code;
}
// -------- bean 对象代理 // -------- bean 对象代理

View File

@ -31,6 +31,7 @@ import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.exception.SaOAuth2RefreshTokenException; import cn.dev33.satoken.oauth2.exception.SaOAuth2RefreshTokenException;
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 cn.dev33.satoken.util.SaResult;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -58,12 +59,15 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
// 生成新Code // 生成新Code
String codeValue = SaOAuth2Strategy.instance.createCodeValue.execute(ra.clientId, ra.loginId, ra.scopes); String codeValue = SaOAuth2Strategy.instance.createCodeValue.execute(ra.clientId, ra.loginId, ra.scopes);
CodeModel cm = new CodeModel(codeValue, ra.clientId, ra.scopes, ra.loginId, ra.redirectUri); CodeModel cm = new CodeModel(codeValue, ra.clientId, ra.scopes, ra.loginId, ra.redirectUri, ra.getNonce());
// 保存新Code // 保存新Code
dao.saveCode(cm); dao.saveCode(cm);
dao.saveCodeIndex(cm); dao.saveCodeIndex(cm);
// 保存code-nonce
dao.saveCodeNonceIndex(cm);
// 返回 // 返回
return cm; return cm;
} }

View File

@ -52,6 +52,11 @@ public class CodeModel implements Serializable {
* 重定向的地址 * 重定向的地址
*/ */
public String redirectUri; public String redirectUri;
/**
* 随机数
*/
public String nonce;
/** /**
* 构建一个 * 构建一个
@ -67,13 +72,14 @@ public class CodeModel implements Serializable {
* @param loginId 对应的账号id * @param loginId 对应的账号id
* @param redirectUri 重定向地址 * @param redirectUri 重定向地址
*/ */
public CodeModel(String code, String clientId, List<String> scopes, Object loginId, String redirectUri) { public CodeModel(String code, String clientId, List<String> scopes, Object loginId, String redirectUri, String nonce) {
super(); super();
this.code = code; this.code = code;
this.clientId = clientId; this.clientId = clientId;
this.scopes = scopes; this.scopes = scopes;
this.loginId = loginId; this.loginId = loginId;
this.redirectUri = redirectUri; this.redirectUri = redirectUri;
this.nonce = nonce;
} }
public String getCode() { public String getCode() {
@ -121,10 +127,19 @@ public class CodeModel implements Serializable {
return this; return this;
} }
public String getNonce() {
return nonce;
}
public CodeModel setNonce(String nonce) {
this.nonce = nonce;
return this;
}
@Override @Override
public String toString() { public String toString() {
return "CodeModel [code=" + code + ", clientId=" + clientId + ", scopes=" + scopes + ", loginId=" + loginId return "CodeModel [code=" + code + ", clientId=" + clientId + ", scopes=" + scopes + ", loginId=" + loginId
+ ", redirectUri=" + redirectUri + "]"; + ", redirectUri=" + redirectUri + ", nonce=" + nonce + " ]";
} }
} }

View File

@ -62,6 +62,11 @@ public class RequestAuthModel implements Serializable {
*/ */
public String state; public String state;
/**
* 随机数
*/
public String nonce;
/** /**
* @return clientId * @return clientId
@ -158,7 +163,23 @@ public class RequestAuthModel implements Serializable {
this.state = state; this.state = state;
return this; return this;
} }
/**
* @return nonce
*/
public String getNonce() {
return nonce;
}
/**
* @param nonce 要设置的随机数
* @return 对象自身
*/
public RequestAuthModel setNonce(String nonce) {
this.nonce = nonce;
return this;
}
/** /**
* 检查此Model参数是否有效 * 检查此Model参数是否有效
* @return 对象自身 * @return 对象自身

View File

@ -136,6 +136,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
ra.responseType = req.getParamNotNull(Param.response_type); ra.responseType = req.getParamNotNull(Param.response_type);
ra.redirectUri = req.getParamNotNull(Param.redirect_uri); ra.redirectUri = req.getParamNotNull(Param.redirect_uri);
ra.state = req.getParam(Param.state); ra.state = req.getParam(Param.state);
ra.nonce = req.getParam(Param.nonce);
ra.scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(req.getParam(Param.scope)); ra.scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(req.getParam(Param.scope));
ra.loginId = loginId; ra.loginId = loginId;
return ra; return ra;

View File

@ -22,6 +22,8 @@ import cn.dev33.satoken.jwt.SaJwtUtil;
import cn.dev33.satoken.jwt.error.SaJwtErrorCode; import cn.dev33.satoken.jwt.error.SaJwtErrorCode;
import cn.dev33.satoken.jwt.exception.SaJwtException; import cn.dev33.satoken.jwt.exception.SaJwtException;
import cn.dev33.satoken.oauth2.SaOAuth2Manager; import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.dao.SaOAuth2Dao;
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.oidc.IdTokenModel; import cn.dev33.satoken.oauth2.data.model.oidc.IdTokenModel;
@ -104,7 +106,12 @@ public class OidcScopeHandler implements SaOAuth2ScopeHandlerInterface {
* @return / * @return /
*/ */
public String getNonce() { public String getNonce() {
String nonce = SaHolder.getRequest().getParam("nonce"); String nonce = SaHolder.getRequest().getParam(SaOAuth2Consts.Param.nonce);
if(SaFoxUtil.isEmpty(nonce)) {
//通过code查找nonce
//为了避免其它handler可能会用到nonce,任由其自然过期只取用不删除
nonce = SaOAuth2Manager.getDao().getNonce(SaHolder.getRequest().getParam(SaOAuth2Consts.Param.code));
}
if(SaFoxUtil.isEmpty(nonce)) { if(SaFoxUtil.isEmpty(nonce)) {
nonce = SaFoxUtil.getRandomString(32); nonce = SaFoxUtil.getRandomString(32);
} }