mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-05-03 04:13:46 +08:00
将 scope 字段改为 List 类型
This commit is contained in:
parent
47cf8939cb
commit
15e2d9f668
@ -29,7 +29,6 @@ import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Sa-Token 内部工具类
|
||||
@ -563,7 +562,7 @@ public class SaFoxUtil {
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String convertListToString(List<?> list) {
|
||||
if(list == null || list.size() == 0) {
|
||||
if(list == null || list.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
@ -5,6 +5,8 @@ import cn.dev33.satoken.oauth2.data.model.SaClientModel;
|
||||
import cn.dev33.satoken.secure.SaSecureUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Sa-Token OAuth2:自定义数据加载器
|
||||
*
|
||||
@ -22,7 +24,7 @@ public class SaOAuth2DataLoaderImpl implements SaOAuth2DataLoader {
|
||||
.setClientId("1001")
|
||||
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee")
|
||||
.setAllowUrl("*")
|
||||
.setContractScope("userinfo")
|
||||
.setContractScopes(Arrays.asList("userinfo"))
|
||||
.setIsAutoMode(true);
|
||||
}
|
||||
return null;
|
||||
|
@ -34,27 +34,25 @@ public class SaOAuth2ServerController {
|
||||
// Sa-OAuth2 定制化配置
|
||||
@Autowired
|
||||
public void setSaOAuth2Config(SaOAuth2Config cfg) {
|
||||
cfg.
|
||||
// 未登录的视图
|
||||
setNotLoginView(()->{
|
||||
return new ModelAndView("login.html");
|
||||
}).
|
||||
// 未登录的视图
|
||||
cfg.notLoginView = ()->{
|
||||
return new ModelAndView("login.html");
|
||||
};
|
||||
// 登录处理函数
|
||||
setDoLoginHandle((name, pwd) -> {
|
||||
if("sa".equals(name) && "123456".equals(pwd)) {
|
||||
StpUtil.login(10001);
|
||||
return SaResult.ok();
|
||||
}
|
||||
return SaResult.error("账号名或密码错误");
|
||||
}).
|
||||
cfg.doLoginHandle = (name, pwd) -> {
|
||||
if("sa".equals(name) && "123456".equals(pwd)) {
|
||||
StpUtil.login(10001);
|
||||
return SaResult.ok();
|
||||
}
|
||||
return SaResult.error("账号名或密码错误");
|
||||
};
|
||||
// 授权确认视图
|
||||
setConfirmView((clientId, scope)->{
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("clientId", clientId);
|
||||
map.put("scope", scope);
|
||||
return new ModelAndView("confirm.html", map);
|
||||
})
|
||||
;
|
||||
cfg.confirmView = (clientId, scope)->{
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("clientId", clientId);
|
||||
map.put("scope", scope);
|
||||
return new ModelAndView("confirm.html", map);
|
||||
};
|
||||
}
|
||||
|
||||
// 全局异常拦截
|
||||
|
@ -16,6 +16,8 @@
|
||||
package cn.dev33.satoken.oauth2;
|
||||
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
|
||||
import cn.dev33.satoken.oauth2.data.convert.SaOAuth2DataConverter;
|
||||
import cn.dev33.satoken.oauth2.data.convert.SaOAuth2DataConverterDefaultImpl;
|
||||
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
|
||||
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoaderDefaultImpl;
|
||||
import cn.dev33.satoken.oauth2.data.resolver.SaOAuth2DataResolver;
|
||||
@ -84,4 +86,22 @@ public class SaOAuth2Manager {
|
||||
SaOAuth2Manager.dataResolver = dataResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth2 数据格式转换器
|
||||
*/
|
||||
private static volatile SaOAuth2DataConverter dataConverter;
|
||||
public static SaOAuth2DataConverter getDataConverter() {
|
||||
if (dataConverter == null) {
|
||||
synchronized (SaOAuth2Manager.class) {
|
||||
if (dataConverter == null) {
|
||||
setDataConverter(new SaOAuth2DataConverterDefaultImpl());
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataConverter;
|
||||
}
|
||||
public static void setDataConverter(SaOAuth2DataConverter dataConverter) {
|
||||
SaOAuth2Manager.dataConverter = dataConverter;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,11 +15,12 @@
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.config;
|
||||
|
||||
import cn.dev33.satoken.oauth2.function.SaOAuth2ConfirmViewFunction;
|
||||
import cn.dev33.satoken.oauth2.function.SaOAuth2DoLoginHandleFunction;
|
||||
import cn.dev33.satoken.oauth2.function.SaOAuth2NotLoginViewFunction;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Sa-Token-OAuth2 配置类 Model
|
||||
@ -218,65 +219,17 @@ public class SaOAuth2Config implements Serializable {
|
||||
/**
|
||||
* OAuth-Server端:未登录时返回的View
|
||||
*/
|
||||
public Supplier<Object> notLoginView = () -> "当前会话在OAuth-Server认证中心尚未登录";
|
||||
public SaOAuth2NotLoginViewFunction notLoginView = () -> "当前会话在OAuth-Server认证中心尚未登录";
|
||||
|
||||
/**
|
||||
* OAuth-Server端:确认授权时返回的View
|
||||
*/
|
||||
public BiFunction<String, String, Object> confirmView = (clientId, scope) -> "本次操作需要用户授权";
|
||||
public SaOAuth2ConfirmViewFunction confirmView = (clientId, scopes) -> "本次操作需要用户授权";
|
||||
|
||||
/**
|
||||
* OAuth-Server端:登录函数
|
||||
*/
|
||||
public BiFunction<String, String, Object> doLoginHandle = (name, pwd) -> SaResult.error();
|
||||
|
||||
/**
|
||||
* @param notLoginView OAuth-Server端:未登录时返回的View
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2Config setNotLoginView(Supplier<Object> notLoginView) {
|
||||
this.notLoginView = notLoginView;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 函数 OAuth-Server端:未登录时返回的View
|
||||
*/
|
||||
public Supplier<Object> getNotLoginView() {
|
||||
return notLoginView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param confirmView OAuth-Server端:确认授权时返回的View
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2Config setConfirmView(BiFunction<String, String, Object> confirmView) {
|
||||
this.confirmView = confirmView;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 函数 OAuth-Server端:确认授权时返回的View
|
||||
*/
|
||||
public BiFunction<String, String, Object> getConfirmView() {
|
||||
return confirmView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param doLoginHandle OAuth-Server端:登录函数
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2Config setDoLoginHandle(BiFunction<String, String, Object> doLoginHandle) {
|
||||
this.doLoginHandle = doLoginHandle;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 函数 OAuth-Server端:登录函数
|
||||
*/
|
||||
public BiFunction<String, String, Object> getDoLoginHandle() {
|
||||
return doLoginHandle;
|
||||
}
|
||||
public SaOAuth2DoLoginHandleFunction doLoginHandle = (name, pwd) -> SaResult.error();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.data.convert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sa-Token OAuth2 数据格式转换器
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
public interface SaOAuth2DataConverter {
|
||||
|
||||
/**
|
||||
* 转换 scope 数据格式:String -> List
|
||||
* @param scopeString /
|
||||
* @return /
|
||||
*/
|
||||
List<String> convertScopeStringToList(String scopeString);
|
||||
|
||||
/**
|
||||
* 转换 scope 数据格式:List -> String
|
||||
* @param scopeList /
|
||||
* @return /
|
||||
*/
|
||||
String convertScopeListToString(List<String> scopeList);
|
||||
|
||||
/**
|
||||
* 转换 AllowUrl 数据格式:String -> List
|
||||
* @param allowUrl /
|
||||
* @return /
|
||||
*/
|
||||
List<String> convertAllowUrlStringToList(String allowUrl);
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.data.convert;
|
||||
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sa-Token OAuth2 数据格式转换器,默认实现类
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
|
||||
|
||||
/**
|
||||
* 转换 scope 数据格式:String -> List
|
||||
*/
|
||||
@Override
|
||||
public List<String> convertScopeStringToList(String scopeString) {
|
||||
if(SaFoxUtil.isEmpty(scopeString)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 兼容以下三种分隔符:空格、逗号、%20
|
||||
scopeString = scopeString.replaceAll(" ", ",");
|
||||
scopeString = scopeString.replaceAll("%20", ",");
|
||||
return SaFoxUtil.convertStringToList(scopeString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换 scope 数据格式:List -> String
|
||||
*/
|
||||
@Override
|
||||
public String convertScopeListToString(List<String> scopeList) {
|
||||
return SaFoxUtil.convertListToString(scopeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换 AllowUrl 数据格式:String -> List
|
||||
*/
|
||||
@Override
|
||||
public List<String> convertAllowUrlStringToList(String allowUrl) {
|
||||
if(SaFoxUtil.isEmpty(allowUrl)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return SaFoxUtil.convertStringToList(allowUrl);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package cn.dev33.satoken.oauth2.data.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -67,31 +68,106 @@ public class AccessTokenModel implements Serializable {
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
public String scope;
|
||||
public List<String> scopes;
|
||||
|
||||
public AccessTokenModel() {}
|
||||
|
||||
/**
|
||||
* 构建一个
|
||||
* @param accessToken accessToken
|
||||
* @param clientId 应用id
|
||||
* @param scope 请求授权范围
|
||||
* @param scopes 请求授权范围
|
||||
* @param loginId 对应的账号id
|
||||
*/
|
||||
public AccessTokenModel(String accessToken, String clientId, Object loginId, String scope) {
|
||||
public AccessTokenModel(String accessToken, String clientId, Object loginId, List<String> scopes) {
|
||||
super();
|
||||
this.accessToken = accessToken;
|
||||
this.clientId = clientId;
|
||||
this.loginId = loginId;
|
||||
this.scope = scope;
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public AccessTokenModel setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public AccessTokenModel setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getExpiresTime() {
|
||||
return expiresTime;
|
||||
}
|
||||
|
||||
public AccessTokenModel setExpiresTime(long expiresTime) {
|
||||
this.expiresTime = expiresTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getRefreshExpiresTime() {
|
||||
return refreshExpiresTime;
|
||||
}
|
||||
|
||||
public AccessTokenModel setRefreshExpiresTime(long refreshExpiresTime) {
|
||||
this.refreshExpiresTime = refreshExpiresTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public AccessTokenModel setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object getLoginId() {
|
||||
return loginId;
|
||||
}
|
||||
|
||||
public AccessTokenModel setLoginId(Object loginId) {
|
||||
this.loginId = loginId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public AccessTokenModel setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getScopes() {
|
||||
return scopes;
|
||||
}
|
||||
|
||||
public AccessTokenModel setScopes(List<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccessTokenModel [accessToken=" + accessToken + ", refreshToken=" + refreshToken
|
||||
+ ", accessTokenTimeout=" + expiresTime + ", refreshTokenTimeout=" + refreshExpiresTime
|
||||
+ ", clientId=" + clientId + ", scope=" + scope + ", openid=" + openid + "]";
|
||||
+ ", clientId=" + clientId + ", scopes=" + scopes + ", openid=" + openid + "]";
|
||||
}
|
||||
|
||||
// 追加只读属性
|
||||
|
||||
/**
|
||||
* 获取:此 Access-Token 的剩余有效期(秒)
|
||||
@ -115,6 +191,7 @@ public class AccessTokenModel implements Serializable {
|
||||
* 将所有属性转换为下划线形式的Map
|
||||
* @return 属性转Map
|
||||
*/
|
||||
@Deprecated
|
||||
public Map<String, Object> toLineMap() {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("access_token", accessToken);
|
||||
@ -122,7 +199,7 @@ public class AccessTokenModel implements Serializable {
|
||||
map.put("expires_in", getExpiresIn());
|
||||
map.put("refresh_expires_in", getRefreshExpiresIn());
|
||||
map.put("client_id", clientId);
|
||||
map.put("scope", scope);
|
||||
map.put("scopes", scopes);
|
||||
map.put("openid", openid);
|
||||
return map;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package cn.dev33.satoken.oauth2.data.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -47,7 +48,7 @@ public class ClientTokenModel implements Serializable {
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
public String scope;
|
||||
public List<String> scopes;
|
||||
|
||||
public ClientTokenModel() {}
|
||||
|
||||
@ -55,19 +56,19 @@ public class ClientTokenModel implements Serializable {
|
||||
* 构建一个
|
||||
* @param accessToken accessToken
|
||||
* @param clientId 应用id
|
||||
* @param scope 请求授权范围
|
||||
* @param scopes 请求授权范围
|
||||
*/
|
||||
public ClientTokenModel(String accessToken, String clientId, String scope) {
|
||||
public ClientTokenModel(String accessToken, String clientId, List<String> scopes) {
|
||||
super();
|
||||
this.clientToken = accessToken;
|
||||
this.clientId = clientId;
|
||||
this.scope = scope;
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClientTokenModel [clientToken=" + clientToken + ", expiresTime=" + expiresTime + ", clientId="
|
||||
+ clientId + ", scope=" + scope + "]";
|
||||
+ clientId + ", scopes=" + scopes + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,15 +81,16 @@ public class ClientTokenModel implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有属性转换为下划线形式的Map
|
||||
* @return 属性转Map
|
||||
* 将所有属性转换为下划线形式的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("scope", scope);
|
||||
map.put("scopes", scopes);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
package cn.dev33.satoken.oauth2.data.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Model: 授权码
|
||||
@ -40,7 +41,7 @@ public class CodeModel implements Serializable {
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
public String scope;
|
||||
public List<String> scopes;
|
||||
|
||||
/**
|
||||
* 对应账号id
|
||||
@ -62,93 +63,67 @@ public class CodeModel implements Serializable {
|
||||
* 构建一个
|
||||
* @param code 授权码
|
||||
* @param clientId 应用id
|
||||
* @param scope 请求授权范围
|
||||
* @param scopes 请求授权范围
|
||||
* @param loginId 对应的账号id
|
||||
* @param redirectUri 重定向地址
|
||||
*/
|
||||
public CodeModel(String code, String clientId, String scope, Object loginId, String redirectUri) {
|
||||
public CodeModel(String code, String clientId, List<String> scopes, Object loginId, String redirectUri) {
|
||||
super();
|
||||
this.code = code;
|
||||
this.clientId = clientId;
|
||||
this.scope = scope;
|
||||
this.scopes = scopes;
|
||||
this.loginId = loginId;
|
||||
this.redirectUri = redirectUri;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return code
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code 要设置的 code
|
||||
*/
|
||||
public void setCode(String code) {
|
||||
public CodeModel setCode(String code) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return clientId
|
||||
*/
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clientId 要设置的 clientId
|
||||
*/
|
||||
public void setClientId(String clientId) {
|
||||
public CodeModel setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return scope
|
||||
*/
|
||||
public String getScope() {
|
||||
return scope;
|
||||
public List<String> getScopes() {
|
||||
return scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scope 要设置的 scope
|
||||
*/
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
public CodeModel setScopes(List<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return loginId
|
||||
*/
|
||||
public Object getLoginId() {
|
||||
return loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loginId 要设置的 loginId
|
||||
*/
|
||||
public void setLoginId(Object loginId) {
|
||||
public CodeModel setLoginId(Object loginId) {
|
||||
this.loginId = loginId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return redirectUri
|
||||
*/
|
||||
|
||||
public String getRedirectUri() {
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param redirectUri 要设置的 redirectUri
|
||||
*/
|
||||
public void setRedirectUri(String redirectUri) {
|
||||
|
||||
public CodeModel setRedirectUri(String redirectUri) {
|
||||
this.redirectUri = redirectUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CodeModel [code=" + code + ", clientId=" + clientId + ", scope=" + scope + ", loginId=" + loginId
|
||||
return "CodeModel [code=" + code + ", clientId=" + clientId + ", scopes=" + scopes + ", loginId=" + loginId
|
||||
+ ", redirectUri=" + redirectUri + "]";
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
package cn.dev33.satoken.oauth2.data.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Model: Refresh-Token
|
||||
@ -45,7 +46,7 @@ public class RefreshTokenModel implements Serializable {
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
public String scope;
|
||||
public List<String> scopes;
|
||||
|
||||
/**
|
||||
* 对应账号id
|
||||
@ -57,10 +58,64 @@ public class RefreshTokenModel implements Serializable {
|
||||
*/
|
||||
public String openid;
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public RefreshTokenModel setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getExpiresTime() {
|
||||
return expiresTime;
|
||||
}
|
||||
|
||||
public RefreshTokenModel setExpiresTime(long expiresTime) {
|
||||
this.expiresTime = expiresTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public RefreshTokenModel setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getScopes() {
|
||||
return scopes;
|
||||
}
|
||||
|
||||
public RefreshTokenModel setScopes(List<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object getLoginId() {
|
||||
return loginId;
|
||||
}
|
||||
|
||||
public RefreshTokenModel setLoginId(Object loginId) {
|
||||
this.loginId = loginId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public RefreshTokenModel setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RefreshTokenModel [refreshToken=" + refreshToken + ", expiresTime=" + expiresTime
|
||||
+ ", clientId=" + clientId + ", scope=" + scope + ", loginId=" + loginId + ", openid=" + openid + "]";
|
||||
+ ", clientId=" + clientId + ", scopes=" + scopes + ", loginId=" + loginId + ", openid=" + openid + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,7 @@
|
||||
package cn.dev33.satoken.oauth2.data.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
|
||||
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
|
||||
@ -39,7 +40,7 @@ public class RequestAuthModel implements Serializable {
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
public String scope;
|
||||
public List<String> scopes;
|
||||
|
||||
/**
|
||||
* 对应的账号id
|
||||
@ -79,18 +80,18 @@ public class RequestAuthModel implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return scope
|
||||
* @return scopes
|
||||
*/
|
||||
public String getScope() {
|
||||
return scope;
|
||||
public List<String> getScopes() {
|
||||
return scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scope 要设置的 scope
|
||||
* @param scopes 要设置的 scopes
|
||||
* @return 对象自身
|
||||
*/
|
||||
public RequestAuthModel setScope(String scope) {
|
||||
this.scope = scope;
|
||||
public RequestAuthModel setScopes(List<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -166,7 +167,7 @@ public class RequestAuthModel implements Serializable {
|
||||
if(SaFoxUtil.isEmpty(clientId)) {
|
||||
throw new SaOAuth2Exception("client_id 不可为空").setCode(SaOAuth2ErrorCode.CODE_30101);
|
||||
}
|
||||
if(SaFoxUtil.isEmpty(scope)) {
|
||||
if(SaFoxUtil.isEmpty(scopes)) {
|
||||
throw new SaOAuth2Exception("scope 不可为空").setCode(SaOAuth2ErrorCode.CODE_30102);
|
||||
}
|
||||
if(SaFoxUtil.isEmpty(redirectUri)) {
|
||||
|
@ -15,11 +15,12 @@
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.data.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Client应用信息 Model
|
||||
*
|
||||
@ -43,7 +44,7 @@ public class SaClientModel implements Serializable {
|
||||
/**
|
||||
* 应用签约的所有权限, 多个用逗号隔开
|
||||
*/
|
||||
public String contractScope;
|
||||
public List<String> contractScopes;
|
||||
|
||||
/**
|
||||
* 应用允许授权的所有URL, 多个用逗号隔开
|
||||
@ -93,11 +94,11 @@ public class SaClientModel implements Serializable {
|
||||
this.clientTokenTimeout = config.getClientTokenTimeout();
|
||||
this.pastClientTokenTimeout = config.getPastClientTokenTimeout();
|
||||
}
|
||||
public SaClientModel(String clientId, String clientSecret, String contractScope, String allowUrl) {
|
||||
public SaClientModel(String clientId, String clientSecret, List<String> contractScopes, String allowUrl) {
|
||||
super();
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
this.contractScope = contractScope;
|
||||
this.contractScopes = contractScopes;
|
||||
this.allowUrl = allowUrl;
|
||||
}
|
||||
|
||||
@ -134,18 +135,18 @@ public class SaClientModel implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 应用签约的所有权限, 多个用逗号隔开
|
||||
* @return 应用签约的所有权限
|
||||
*/
|
||||
public String getContractScope() {
|
||||
return contractScope;
|
||||
public List<String> getContractScopes() {
|
||||
return contractScopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contractScope 应用签约的所有权限, 多个用逗号隔开
|
||||
* @param contractScopes 应用签约的所有权限, 多个用逗号隔开
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaClientModel setContractScope(String contractScope) {
|
||||
this.contractScope = contractScope;
|
||||
public SaClientModel setContractScopes(List<String> contractScopes) {
|
||||
this.contractScopes = contractScopes;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -329,8 +330,8 @@ public class SaClientModel implements Serializable {
|
||||
//
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaClientModel [clientId=" + clientId + ", clientSecret=" + clientSecret + ", contractScope="
|
||||
+ contractScope + ", allowUrl=" + allowUrl + ", isCode=" + isCode + ", isImplicit=" + isImplicit
|
||||
return "SaClientModel [clientId=" + clientId + ", clientSecret=" + clientSecret + ", contractScopes="
|
||||
+ contractScopes + ", allowUrl=" + allowUrl + ", isCode=" + isCode + ", isImplicit=" + isImplicit
|
||||
+ ", isPassword=" + isPassword + ", isClient=" + isClient + ", isAutoMode=" + isAutoMode
|
||||
+ ", isNewRefresh=" + isNewRefresh + ", accessTokenTimeout=" + accessTokenTimeout
|
||||
+ ", refreshTokenTimeout=" + refreshTokenTimeout + ", clientTokenTimeout=" + clientTokenTimeout
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.data.resolver;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.TokenType;
|
||||
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
|
||||
@ -44,7 +45,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
|
||||
map.put("expires_in", at.getExpiresIn());
|
||||
map.put("refresh_expires_in", at.getRefreshExpiresIn());
|
||||
map.put("client_id", at.clientId);
|
||||
map.put("scope", at.scope);
|
||||
map.put("scope", SaOAuth2Manager.getDataConverter().convertScopeListToString(at.scopes));
|
||||
map.put("openid", at.openid);
|
||||
return SaResult.ok().setMap(map);
|
||||
}
|
||||
@ -59,7 +60,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
|
||||
map.put("access_token", ct.clientToken); // 兼容 OAuth2 协议
|
||||
map.put("expires_in", ct.getExpiresIn());
|
||||
map.put("client_id", ct.clientId);
|
||||
map.put("scope", ct.scope);
|
||||
map.put("scope", SaOAuth2Manager.getDataConverter().convertScopeListToString(ct.scopes));
|
||||
return SaResult.ok().setMap(map);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* 函数式接口:OAuth-Server端 确认授权时返回的View
|
||||
*
|
||||
* <p> 参数:无 </p>
|
||||
* <p> 返回:view 视图 </p>
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SaOAuth2ConfirmViewFunction extends BiFunction<String, List<String>, Object> {
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* 函数式接口:登录函数
|
||||
*
|
||||
* <p> 参数:name, pwd </p>
|
||||
* <p> 返回:认证返回结果 </p>
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SaOAuth2DoLoginHandleFunction extends BiFunction<String, String, Object> {
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 函数式接口:OAuth-Server端 未登录时返回的View
|
||||
*
|
||||
* <p> 参数:clientId, scope </p>
|
||||
* <p> 返回:view 视图 </p>
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SaOAuth2NotLoginViewFunction extends Supplier<Object> {
|
||||
|
||||
}
|
@ -35,6 +35,8 @@ import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sa-Token OAuth2 请求处理器
|
||||
*
|
||||
@ -142,7 +144,7 @@ public class SaOAuth2ServerProcessor {
|
||||
|
||||
// 1、如果尚未登录, 则先去登录
|
||||
if( ! getStpLogic().isLogin()) {
|
||||
return cfg.getNotLoginView().get();
|
||||
return cfg.notLoginView.get();
|
||||
}
|
||||
|
||||
// 2、构建请求Model
|
||||
@ -152,12 +154,12 @@ public class SaOAuth2ServerProcessor {
|
||||
oauth2Template.checkRightUrl(ra.clientId, ra.redirectUri);
|
||||
|
||||
// 4、校验:此次申请的Scope,该Client是否已经签约
|
||||
oauth2Template.checkContract(ra.clientId, ra.scope);
|
||||
oauth2Template.checkContract(ra.clientId, ra.scopes);
|
||||
|
||||
// 5、判断:如果此次申请的Scope,该用户尚未授权,则转到授权页面
|
||||
boolean isGrant = oauth2Template.isGrant(ra.loginId, ra.clientId, ra.scope);
|
||||
boolean isGrant = oauth2Template.isGrant(ra.loginId, ra.clientId, ra.scopes);
|
||||
if( ! isGrant) {
|
||||
return cfg.getConfirmView().apply(ra.clientId, ra.scope);
|
||||
return cfg.confirmView.apply(ra.clientId, ra.scopes);
|
||||
}
|
||||
|
||||
// 6、判断授权类型
|
||||
@ -275,7 +277,7 @@ public class SaOAuth2ServerProcessor {
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
|
||||
|
||||
return cfg.getDoLoginHandle().apply(req.getParamNotNull(Param.name), req.getParamNotNull(Param.pwd));
|
||||
return cfg.doLoginHandle.apply(req.getParamNotNull(Param.name), req.getParamNotNull(Param.pwd));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,8 +290,9 @@ public class SaOAuth2ServerProcessor {
|
||||
|
||||
String clientId = req.getParamNotNull(Param.client_id);
|
||||
String scope = req.getParamNotNull(Param.scope);
|
||||
List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
|
||||
Object loginId = getStpLogic().getLoginId();
|
||||
oauth2Template.saveGrantScope(clientId, loginId, scope);
|
||||
oauth2Template.saveGrantScope(clientId, loginId, scopes);
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
@ -308,15 +311,16 @@ public class SaOAuth2ServerProcessor {
|
||||
String clientId = req.getParamNotNull(Param.client_id);
|
||||
String clientSecret = req.getParamNotNull(Param.client_secret);
|
||||
String scope = req.getParam(Param.scope, "");
|
||||
List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
|
||||
|
||||
// 2、校验 ClientScope 和 scope
|
||||
oauth2Template.checkClientSecretAndScope(clientId, clientSecret, scope);
|
||||
oauth2Template.checkClientSecretAndScope(clientId, clientSecret, scopes);
|
||||
|
||||
// 3、防止因前端误传token造成逻辑干扰
|
||||
// SaHolder.getStorage().set(getStpLogic().stpLogic.splicingKeyJustCreatedSave(), "no-token");
|
||||
|
||||
// 3、调用API 开始登录,如果没能成功登录,则直接退出
|
||||
Object retObj = cfg.getDoLoginHandle().apply(username, password);
|
||||
Object retObj = cfg.doLoginHandle.apply(username, password);
|
||||
if( ! getStpLogic().isLogin()) {
|
||||
return retObj;
|
||||
}
|
||||
@ -325,7 +329,7 @@ public class SaOAuth2ServerProcessor {
|
||||
RequestAuthModel ra = new RequestAuthModel();
|
||||
ra.clientId = clientId;
|
||||
ra.loginId = getStpLogic().getLoginId();
|
||||
ra.scope = scope;
|
||||
ra.scopes = scopes;
|
||||
|
||||
// 5、生成 Access-Token
|
||||
AccessTokenModel at = oauth2Template.generateAccessToken(ra, true);
|
||||
@ -345,16 +349,17 @@ public class SaOAuth2ServerProcessor {
|
||||
// 获取参数
|
||||
String clientId = req.getParamNotNull(Param.client_id);
|
||||
String clientSecret = req.getParamNotNull(Param.client_secret);
|
||||
String scope = req.getParam(Param.scope);
|
||||
String scope = req.getParam(Param.scope, "");
|
||||
List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
|
||||
|
||||
//校验 ClientScope
|
||||
oauth2Template.checkContract(clientId, scope);
|
||||
oauth2Template.checkContract(clientId, scopes);
|
||||
|
||||
// 校验 ClientSecret
|
||||
oauth2Template.checkClientSecret(clientId, clientSecret);
|
||||
|
||||
// 生成
|
||||
ClientTokenModel ct = oauth2Template.generateClientToken(clientId, scope);
|
||||
ClientTokenModel ct = oauth2Template.generateClientToken(clientId, scopes);
|
||||
|
||||
// 返回
|
||||
return SaOAuth2Manager.getDataResolver().buildClientTokenReturnValue(ct);
|
||||
|
@ -25,6 +25,7 @@ import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
|
||||
import cn.dev33.satoken.strategy.SaStrategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -107,7 +108,7 @@ public class SaOAuth2Template {
|
||||
return;
|
||||
}
|
||||
AccessTokenModel at = checkAccessToken(accessToken);
|
||||
List<String> scopeList = SaFoxUtil.convertStringToList(at.scope);
|
||||
List<String> scopeList = at.scopes;
|
||||
for (String scope : scopes) {
|
||||
SaOAuth2Exception.throwBy( ! scopeList.contains(scope), "该 Access-Token 不具备 Scope:" + scope, SaOAuth2ErrorCode.CODE_30108);
|
||||
}
|
||||
@ -122,7 +123,7 @@ public class SaOAuth2Template {
|
||||
return;
|
||||
}
|
||||
ClientTokenModel ct = checkClientToken(clientToken);
|
||||
List<String> scopeList = SaFoxUtil.convertStringToList(ct.scope);
|
||||
List<String> scopeList = ct.scopes;
|
||||
for (String scope : scopes) {
|
||||
SaOAuth2Exception.throwBy( ! scopeList.contains(scope), "该 Client-Token 不具备 Scope:" + scope, SaOAuth2ErrorCode.CODE_30109);
|
||||
}
|
||||
@ -141,7 +142,9 @@ public class SaOAuth2Template {
|
||||
ra.responseType = req.getParamNotNull(Param.response_type);
|
||||
ra.redirectUri = req.getParamNotNull(Param.redirect_uri);
|
||||
ra.state = req.getParam(Param.state);
|
||||
ra.scope = req.getParam(Param.scope, "");
|
||||
// 数据解析
|
||||
String scope = req.getParam(Param.scope, "");
|
||||
ra.scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
|
||||
ra.loginId = loginId;
|
||||
return ra;
|
||||
}
|
||||
@ -156,8 +159,8 @@ public class SaOAuth2Template {
|
||||
deleteCode(getCodeValue(ra.clientId, ra.loginId));
|
||||
|
||||
// 生成新Code
|
||||
String code = randomCode(ra.clientId, ra.loginId, ra.scope);
|
||||
CodeModel cm = new CodeModel(code, ra.clientId, ra.scope, ra.loginId, ra.redirectUri);
|
||||
String code = randomCode(ra.clientId, ra.loginId, ra.scopes);
|
||||
CodeModel cm = new CodeModel(code, ra.clientId, ra.scopes, ra.loginId, ra.redirectUri);
|
||||
|
||||
// 保存新Code
|
||||
saveCode(cm);
|
||||
@ -250,8 +253,8 @@ public class SaOAuth2Template {
|
||||
}
|
||||
|
||||
// 2、生成 新Access-Token
|
||||
String newAtValue = randomAccessToken(ra.clientId, ra.loginId, ra.scope);
|
||||
AccessTokenModel at = new AccessTokenModel(newAtValue, ra.clientId, ra.loginId, ra.scope);
|
||||
String newAtValue = randomAccessToken(ra.clientId, ra.loginId, ra.scopes);
|
||||
AccessTokenModel at = new AccessTokenModel(newAtValue, ra.clientId, ra.loginId, ra.scopes);
|
||||
at.openid = getOpenid(ra.clientId, ra.loginId);
|
||||
at.expiresTime = System.currentTimeMillis() + (checkClientModel(ra.clientId).getAccessTokenTimeout() * 1000);
|
||||
|
||||
@ -272,10 +275,10 @@ public class SaOAuth2Template {
|
||||
/**
|
||||
* 构建Model:Client-Token
|
||||
* @param clientId 应用id
|
||||
* @param scope 授权范围
|
||||
* @param scopes 授权范围
|
||||
* @return Client-Token Model
|
||||
*/
|
||||
public ClientTokenModel generateClientToken(String clientId, String scope) {
|
||||
public ClientTokenModel generateClientToken(String clientId, List<String> scopes) {
|
||||
// 1、删掉旧 Past-Token
|
||||
deleteClientToken(getPastTokenValue(clientId));
|
||||
|
||||
@ -291,7 +294,7 @@ public class SaOAuth2Template {
|
||||
}
|
||||
|
||||
// 3、生成新Client-Token
|
||||
ClientTokenModel ct = new ClientTokenModel(randomClientToken(clientId, scope), clientId, scope);
|
||||
ClientTokenModel ct = new ClientTokenModel(randomClientToken(clientId, scopes), clientId, scopes);
|
||||
ct.expiresTime = System.currentTimeMillis() + (cm.getClientTokenTimeout() * 1000);
|
||||
|
||||
// 3、保存新Client-Token
|
||||
@ -356,23 +359,21 @@ public class SaOAuth2Template {
|
||||
* 判断:指定 loginId 是否对一个 Client 授权给了指定 Scope
|
||||
* @param loginId 账号id
|
||||
* @param clientId 应用id
|
||||
* @param scope 权限
|
||||
* @param scopes 权限
|
||||
* @return 是否已经授权
|
||||
*/
|
||||
public boolean isGrant(Object loginId, String clientId, String scope) {
|
||||
List<String> grantScopeList = SaFoxUtil.convertStringToList(getGrantScope(clientId, loginId));
|
||||
List<String> scopeList = SaFoxUtil.convertStringToList(scope);
|
||||
return scopeList.size() == 0 || grantScopeList.containsAll(scopeList);
|
||||
public boolean isGrant(Object loginId, String clientId, List<String> scopes) {
|
||||
List<String> grantScopeList = getGrantScope(clientId, loginId);
|
||||
return scopes.isEmpty() || new HashSet<>(grantScopeList).containsAll(scopes);
|
||||
}
|
||||
/**
|
||||
* 校验:该Client是否签约了指定的Scope
|
||||
* @param clientId 应用id
|
||||
* @param scope 权限(多个用逗号隔开)
|
||||
* @param scopes 权限(多个用逗号隔开)
|
||||
*/
|
||||
public void checkContract(String clientId, String scope) {
|
||||
List<String> clientScopeList = SaFoxUtil.convertStringToList(checkClientModel(clientId).contractScope);
|
||||
List<String> scopelist = SaFoxUtil.convertStringToList(scope);
|
||||
if( ! clientScopeList.containsAll(scopelist)) {
|
||||
public void checkContract(String clientId, List<String> scopes) {
|
||||
List<String> clientScopeList = checkClientModel(clientId).contractScopes;
|
||||
if( ! new HashSet<>(clientScopeList).containsAll(scopes)) {
|
||||
throw new SaOAuth2Exception("请求的Scope暂未签约").setCode(SaOAuth2ErrorCode.CODE_30112);
|
||||
}
|
||||
}
|
||||
@ -394,7 +395,8 @@ public class SaOAuth2Template {
|
||||
}
|
||||
|
||||
// 3、是否在[允许地址列表]之中
|
||||
List<String> allowList = SaFoxUtil.convertStringToList(checkClientModel(clientId).allowUrl);
|
||||
SaClientModel clientModel = checkClientModel(clientId);
|
||||
List<String> allowList = SaOAuth2Manager.getDataConverter().convertAllowUrlStringToList(clientModel.allowUrl);
|
||||
if( ! SaStrategy.instance.hasElement.apply(allowList, url)) {
|
||||
throw new SaOAuth2Exception("非法redirect_url:" + url).setCode(SaOAuth2ErrorCode.CODE_30114);
|
||||
}
|
||||
@ -415,16 +417,15 @@ public class SaOAuth2Template {
|
||||
* 校验:clientId 与 clientSecret 是否正确,并且是否签约了指定 scopes
|
||||
* @param clientId 应用id
|
||||
* @param clientSecret 秘钥
|
||||
* @param scopes 权限(多个用逗号隔开)
|
||||
* @param scopes 权限
|
||||
* @return SaClientModel对象
|
||||
*/
|
||||
public SaClientModel checkClientSecretAndScope(String clientId, String clientSecret, String scopes) {
|
||||
public SaClientModel checkClientSecretAndScope(String clientId, String clientSecret, List<String> scopes) {
|
||||
// 先校验 clientSecret
|
||||
SaClientModel cm = checkClientSecret(clientId, clientSecret);
|
||||
// 再校验 是否签约
|
||||
List<String> clientScopeList = SaFoxUtil.convertStringToList(cm.contractScope);
|
||||
List<String> scopelist = SaFoxUtil.convertStringToList(scopes);
|
||||
if( ! clientScopeList.containsAll(scopelist)) {
|
||||
List<String> clientScopeList = cm.contractScopes;
|
||||
if( ! new HashSet<>(clientScopeList).containsAll(scopes)) {
|
||||
throw new SaOAuth2Exception("请求的Scope暂未签约").setCode(SaOAuth2ErrorCode.CODE_30116);
|
||||
}
|
||||
// 返回数据
|
||||
@ -504,11 +505,11 @@ public class SaOAuth2Template {
|
||||
*/
|
||||
public AccessTokenModel convertCodeToAccessToken(CodeModel cm) {
|
||||
AccessTokenModel at = new AccessTokenModel();
|
||||
at.accessToken = randomAccessToken(cm.clientId, cm.loginId, cm.scope);
|
||||
at.accessToken = randomAccessToken(cm.clientId, cm.loginId, cm.scopes);
|
||||
// at.refreshToken = randomRefreshToken(cm.clientId, cm.loginId, cm.scope);
|
||||
at.clientId = cm.clientId;
|
||||
at.loginId = cm.loginId;
|
||||
at.scope = cm.scope;
|
||||
at.scopes = cm.scopes;
|
||||
at.openid = getOpenid(cm.clientId, cm.loginId);
|
||||
at.expiresTime = System.currentTimeMillis() + (checkClientModel(cm.clientId).getAccessTokenTimeout() * 1000);
|
||||
// at.refreshExpiresTime = System.currentTimeMillis() + (checkClientModel(cm.clientId).getRefreshTokenTimeout() * 1000);
|
||||
@ -521,10 +522,10 @@ public class SaOAuth2Template {
|
||||
*/
|
||||
public RefreshTokenModel convertAccessTokenToRefreshToken(AccessTokenModel at) {
|
||||
RefreshTokenModel rt = new RefreshTokenModel();
|
||||
rt.refreshToken = randomRefreshToken(at.clientId, at.loginId, at.scope);
|
||||
rt.refreshToken = randomRefreshToken(at.clientId, at.loginId, at.scopes);
|
||||
rt.clientId = at.clientId;
|
||||
rt.loginId = at.loginId;
|
||||
rt.scope = at.scope;
|
||||
rt.scopes = at.scopes;
|
||||
rt.openid = at.openid;
|
||||
rt.expiresTime = System.currentTimeMillis() + (checkClientModel(at.clientId).getRefreshTokenTimeout() * 1000);
|
||||
// 改变at属性
|
||||
@ -539,11 +540,11 @@ public class SaOAuth2Template {
|
||||
*/
|
||||
public AccessTokenModel convertRefreshTokenToAccessToken(RefreshTokenModel rt) {
|
||||
AccessTokenModel at = new AccessTokenModel();
|
||||
at.accessToken = randomAccessToken(rt.clientId, rt.loginId, rt.scope);
|
||||
at.accessToken = randomAccessToken(rt.clientId, rt.loginId, rt.scopes);
|
||||
at.refreshToken = rt.refreshToken;
|
||||
at.clientId = rt.clientId;
|
||||
at.loginId = rt.loginId;
|
||||
at.scope = rt.scope;
|
||||
at.scopes = rt.scopes;
|
||||
at.openid = rt.openid;
|
||||
at.expiresTime = System.currentTimeMillis() + (checkClientModel(rt.clientId).getAccessTokenTimeout() * 1000);
|
||||
at.refreshExpiresTime = rt.expiresTime;
|
||||
@ -556,10 +557,10 @@ public class SaOAuth2Template {
|
||||
*/
|
||||
public RefreshTokenModel convertRefreshTokenToRefreshToken(RefreshTokenModel rt) {
|
||||
RefreshTokenModel newRt = new RefreshTokenModel();
|
||||
newRt.refreshToken = randomRefreshToken(rt.clientId, rt.loginId, rt.scope);
|
||||
newRt.refreshToken = randomRefreshToken(rt.clientId, rt.loginId, rt.scopes);
|
||||
newRt.expiresTime = System.currentTimeMillis() + (checkClientModel(rt.clientId).getRefreshTokenTimeout() * 1000);
|
||||
newRt.clientId = rt.clientId;
|
||||
newRt.scope = rt.scope;
|
||||
newRt.scopes = rt.scopes;
|
||||
newRt.loginId = rt.loginId;
|
||||
newRt.openid = rt.openid;
|
||||
return newRt;
|
||||
@ -665,12 +666,13 @@ public class SaOAuth2Template {
|
||||
* 持久化:用户授权记录
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @param scope 权限列表(多个逗号隔开)
|
||||
* @param scopes 权限列表
|
||||
*/
|
||||
public void saveGrantScope(String clientId, Object loginId, String scope) {
|
||||
if( ! SaFoxUtil.isEmpty(scope)) {
|
||||
public void saveGrantScope(String clientId, Object loginId, List<String> scopes) {
|
||||
if( ! SaFoxUtil.isEmpty(scopes)) {
|
||||
long ttl = checkClientModel(clientId).getAccessTokenTimeout();
|
||||
SaManager.getSaTokenDao().set(splicingGrantScopeKey(clientId, loginId), scope, ttl);
|
||||
String value = SaOAuth2Manager.getDataConverter().convertScopeListToString(scopes);
|
||||
SaManager.getSaTokenDao().set(splicingGrantScopeKey(clientId, loginId), value, ttl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -768,8 +770,9 @@ public class SaOAuth2Template {
|
||||
* @param loginId 账号id
|
||||
* @return 权限
|
||||
*/
|
||||
public String getGrantScope(String clientId, Object loginId) {
|
||||
return SaManager.getSaTokenDao().get(splicingGrantScopeKey(clientId, loginId));
|
||||
public List<String> getGrantScope(String clientId, Object loginId) {
|
||||
String value = SaManager.getSaTokenDao().get(splicingGrantScopeKey(clientId, loginId));
|
||||
return SaOAuth2Manager.getDataConverter().convertScopeStringToList(value);
|
||||
}
|
||||
|
||||
// ------------------- delete数据
|
||||
@ -861,39 +864,39 @@ public class SaOAuth2Template {
|
||||
* 随机一个 Code
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @param scope 权限
|
||||
* @param scopes 权限
|
||||
* @return Code
|
||||
*/
|
||||
public String randomCode(String clientId, Object loginId, String scope) {
|
||||
public String randomCode(String clientId, Object loginId, List<String> scopes) {
|
||||
return SaFoxUtil.getRandomString(60);
|
||||
}
|
||||
/**
|
||||
* 随机一个 Access-Token
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @param scope 权限
|
||||
* @param scopes 权限
|
||||
* @return Access-Token
|
||||
*/
|
||||
public String randomAccessToken(String clientId, Object loginId, String scope) {
|
||||
public String randomAccessToken(String clientId, Object loginId, List<String> scopes) {
|
||||
return SaFoxUtil.getRandomString(60);
|
||||
}
|
||||
/**
|
||||
* 随机一个 Refresh-Token
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @param scope 权限
|
||||
* @param scopes 权限
|
||||
* @return Refresh-Token
|
||||
*/
|
||||
public String randomRefreshToken(String clientId, Object loginId, String scope) {
|
||||
public String randomRefreshToken(String clientId, Object loginId, List<String> scopes) {
|
||||
return SaFoxUtil.getRandomString(60);
|
||||
}
|
||||
/**
|
||||
* 随机一个 Client-Token
|
||||
* @param clientId 应用id
|
||||
* @param scope 权限
|
||||
* @param scopes 权限
|
||||
* @return Client-Token
|
||||
*/
|
||||
public String randomClientToken(String clientId, String scope) {
|
||||
public String randomClientToken(String clientId, List<String> scopes) {
|
||||
return SaFoxUtil.getRandomString(60);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@ import cn.dev33.satoken.context.model.SaRequest;
|
||||
import cn.dev33.satoken.oauth2.data.model.*;
|
||||
import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sa-Token-OAuth2 模块 工具类
|
||||
*
|
||||
@ -135,11 +137,11 @@ public class SaOAuth2Util {
|
||||
/**
|
||||
* 构建Model:Client-Token
|
||||
* @param clientId 应用id
|
||||
* @param scope 授权范围
|
||||
* @param scopes 授权范围
|
||||
* @return Client-Token Model
|
||||
*/
|
||||
public static ClientTokenModel generateClientToken(String clientId, String scope) {
|
||||
return SaOAuth2ServerProcessor.instance.oauth2Template.generateClientToken(clientId, scope);
|
||||
public static ClientTokenModel generateClientToken(String clientId, List<String> scopes) {
|
||||
return SaOAuth2ServerProcessor.instance.oauth2Template.generateClientToken(clientId, scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,20 +180,20 @@ public class SaOAuth2Util {
|
||||
* 判断:指定 loginId 是否对一个 Client 授权给了指定 Scope
|
||||
* @param loginId 账号id
|
||||
* @param clientId 应用id
|
||||
* @param scope 权限
|
||||
* @param scopes 权限
|
||||
* @return 是否已经授权
|
||||
*/
|
||||
public static boolean isGrant(Object loginId, String clientId, String scope) {
|
||||
return SaOAuth2ServerProcessor.instance.oauth2Template.isGrant(loginId, clientId, scope);
|
||||
public static boolean isGrant(Object loginId, String clientId, List<String> scopes) {
|
||||
return SaOAuth2ServerProcessor.instance.oauth2Template.isGrant(loginId, clientId, scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验:该Client是否签约了指定的Scope
|
||||
* @param clientId 应用id
|
||||
* @param scope 权限(多个用逗号隔开)
|
||||
* @param scopes 权限(多个用逗号隔开)
|
||||
*/
|
||||
public static void checkContract(String clientId, String scope) {
|
||||
SaOAuth2ServerProcessor.instance.oauth2Template.checkContract(clientId, scope);
|
||||
public static void checkContract(String clientId, List<String> scopes) {
|
||||
SaOAuth2ServerProcessor.instance.oauth2Template.checkContract(clientId, scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,10 +219,10 @@ public class SaOAuth2Util {
|
||||
* 校验:clientId 与 clientSecret 是否正确,并且是否签约了指定 scopes
|
||||
* @param clientId 应用id
|
||||
* @param clientSecret 秘钥
|
||||
* @param scopes 权限(多个用逗号隔开)
|
||||
* @param scopes 权限
|
||||
* @return SaClientModel对象
|
||||
*/
|
||||
public static SaClientModel checkClientSecretAndScope(String clientId, String clientSecret, String scopes) {
|
||||
public static SaClientModel checkClientSecretAndScope(String clientId, String clientSecret, List<String> scopes) {
|
||||
return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientSecretAndScope(clientId, clientSecret, scopes);
|
||||
}
|
||||
|
||||
@ -264,10 +266,10 @@ public class SaOAuth2Util {
|
||||
* 持久化:用户授权记录
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @param scope 权限列表(多个逗号隔开)
|
||||
* @param scopes 权限列表
|
||||
*/
|
||||
public static void saveGrantScope(String clientId, Object loginId, String scope) {
|
||||
SaOAuth2ServerProcessor.instance.oauth2Template.saveGrantScope(clientId, loginId, scope);
|
||||
public static void saveGrantScope(String clientId, Object loginId, List<String> scopes) {
|
||||
SaOAuth2ServerProcessor.instance.oauth2Template.saveGrantScope(clientId, loginId, scopes);
|
||||
}
|
||||
|
||||
|
||||
@ -315,7 +317,7 @@ public class SaOAuth2Util {
|
||||
* @param loginId 账号id
|
||||
* @return 权限
|
||||
*/
|
||||
public static String getGrantScope(String clientId, Object loginId) {
|
||||
public static List<String> getGrantScope(String clientId, Object loginId) {
|
||||
return SaOAuth2ServerProcessor.instance.oauth2Template.getGrantScope(clientId, loginId);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user