2019-01-31 17:44:42 +08:00
|
|
|
package me.zhyd.oauth.utils;
|
|
|
|
|
|
2019-12-12 14:47:57 +08:00
|
|
|
import me.zhyd.oauth.cache.AuthStateCache;
|
2019-01-31 17:44:42 +08:00
|
|
|
import me.zhyd.oauth.config.AuthConfig;
|
2019-09-06 22:19:02 +08:00
|
|
|
import me.zhyd.oauth.config.AuthDefaultSource;
|
2019-06-20 10:10:18 +08:00
|
|
|
import me.zhyd.oauth.config.AuthSource;
|
2019-07-30 21:19:55 +08:00
|
|
|
import me.zhyd.oauth.enums.AuthResponseStatus;
|
2019-06-19 09:56:28 +08:00
|
|
|
import me.zhyd.oauth.exception.AuthException;
|
2019-08-05 22:05:58 +08:00
|
|
|
import me.zhyd.oauth.model.AuthCallback;
|
2019-01-31 17:44:42 +08:00
|
|
|
|
|
|
|
|
/**
|
2019-05-23 09:06:13 +08:00
|
|
|
* 授权配置类的校验器
|
|
|
|
|
*
|
2019-01-31 17:44:42 +08:00
|
|
|
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
2019-07-27 07:55:52 +08:00
|
|
|
* @since 1.6.1-beta
|
2019-01-31 17:44:42 +08:00
|
|
|
*/
|
2019-06-27 19:39:21 +08:00
|
|
|
public class AuthChecker {
|
2019-01-31 17:44:42 +08:00
|
|
|
|
|
|
|
|
/**
|
2019-02-19 14:49:59 +08:00
|
|
|
* 是否支持第三方登录
|
2019-01-31 17:44:42 +08:00
|
|
|
*
|
2019-03-29 15:27:27 +08:00
|
|
|
* @param config config
|
2019-06-19 09:56:28 +08:00
|
|
|
* @param source source
|
2019-01-31 17:44:42 +08:00
|
|
|
* @return true or false
|
2019-07-27 07:55:52 +08:00
|
|
|
* @since 1.6.1-beta
|
2019-01-31 17:44:42 +08:00
|
|
|
*/
|
2019-06-19 09:56:28 +08:00
|
|
|
public static boolean isSupportedAuth(AuthConfig config, AuthSource source) {
|
2021-04-09 08:33:21 +08:00
|
|
|
boolean isSupported = StringUtils.isNotEmpty(config.getClientId())
|
|
|
|
|
&& StringUtils.isNotEmpty(config.getClientSecret());
|
2019-09-06 22:19:02 +08:00
|
|
|
if (isSupported && AuthDefaultSource.ALIPAY == source) {
|
2019-06-19 09:56:28 +08:00
|
|
|
isSupported = StringUtils.isNotEmpty(config.getAlipayPublicKey());
|
|
|
|
|
}
|
2019-09-06 22:19:02 +08:00
|
|
|
if (isSupported && AuthDefaultSource.STACK_OVERFLOW == source) {
|
2019-07-20 17:21:21 +08:00
|
|
|
isSupported = StringUtils.isNotEmpty(config.getStackOverflowKey());
|
|
|
|
|
}
|
2019-12-12 14:47:57 +08:00
|
|
|
if (isSupported && AuthDefaultSource.WECHAT_ENTERPRISE == source) {
|
2019-08-06 15:44:02 +08:00
|
|
|
isSupported = StringUtils.isNotEmpty(config.getAgentId());
|
|
|
|
|
}
|
2021-03-30 23:25:30 +08:00
|
|
|
if (isSupported && (AuthDefaultSource.CODING == source || AuthDefaultSource.OKTA == source)) {
|
|
|
|
|
isSupported = StringUtils.isNotEmpty(config.getDomainPrefix());
|
2020-06-07 16:28:27 +08:00
|
|
|
}
|
2020-12-20 17:14:06 +08:00
|
|
|
if (isSupported && AuthDefaultSource.XMLY == source) {
|
|
|
|
|
isSupported = StringUtils.isNotEmpty(config.getDeviceId()) && null != config.getClientOsType();
|
|
|
|
|
if (isSupported) {
|
|
|
|
|
isSupported = config.getClientOsType() == 3 || StringUtils.isNotEmpty(config.getPackId());
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-19 09:56:28 +08:00
|
|
|
return isSupported;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查配置合法性。针对部分平台, 对redirect uri有特定要求。一般来说redirect uri都是http://,而对于facebook平台, redirect uri 必须是https的链接
|
|
|
|
|
*
|
|
|
|
|
* @param config config
|
|
|
|
|
* @param source source
|
2019-07-27 07:55:52 +08:00
|
|
|
* @since 1.6.1-beta
|
2019-06-19 09:56:28 +08:00
|
|
|
*/
|
2019-06-27 19:39:21 +08:00
|
|
|
public static void checkConfig(AuthConfig config, AuthSource source) {
|
2019-06-19 09:56:28 +08:00
|
|
|
String redirectUri = config.getRedirectUri();
|
2021-04-09 08:33:21 +08:00
|
|
|
if (config.isIgnoreCheckRedirectUri()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isEmpty(redirectUri)) {
|
|
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
|
|
|
|
}
|
2019-12-25 18:28:18 +08:00
|
|
|
if (!GlobalAuthUtils.isHttpProtocol(redirectUri) && !GlobalAuthUtils.isHttpsProtocol(redirectUri)) {
|
2019-12-12 14:47:57 +08:00
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
2019-06-19 09:56:28 +08:00
|
|
|
}
|
2019-06-19 16:48:09 +08:00
|
|
|
// facebook的回调地址必须为https的链接
|
2019-12-25 18:28:18 +08:00
|
|
|
if (AuthDefaultSource.FACEBOOK == source && !GlobalAuthUtils.isHttpsProtocol(redirectUri)) {
|
2019-12-12 14:47:57 +08:00
|
|
|
// Facebook's redirect uri must use the HTTPS protocol
|
|
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
2019-06-19 09:56:28 +08:00
|
|
|
}
|
2019-06-19 16:48:09 +08:00
|
|
|
// 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1
|
2019-12-25 18:28:18 +08:00
|
|
|
if (AuthDefaultSource.ALIPAY == source && GlobalAuthUtils.isLocalHost(redirectUri)) {
|
2019-12-12 14:47:57 +08:00
|
|
|
// The redirect uri of alipay is forbidden to use localhost or 127.0.0.1
|
|
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
2019-06-19 16:48:09 +08:00
|
|
|
}
|
2021-08-25 23:06:29 +08:00
|
|
|
// 微软的回调地址必须为https的链接或者localhost,不允许使用http
|
|
|
|
|
if(AuthDefaultSource.MICROSOFT== source && !GlobalAuthUtils.isHttpsProtocolOrLocalHost(redirectUri) ){
|
|
|
|
|
// Microsoft's redirect uri must use the HTTPS or localhost
|
|
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
|
|
|
|
}
|
|
|
|
|
// 微软中国的回调地址必须为https的链接或者localhost,不允许使用http
|
|
|
|
|
if(AuthDefaultSource.MICROSOFT_CN== source && !GlobalAuthUtils.isHttpsProtocolOrLocalHost(redirectUri) ){
|
|
|
|
|
// Microsoft's redirect uri must use the HTTPS or localhost
|
|
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
|
|
|
|
}
|
2019-01-31 17:44:42 +08:00
|
|
|
}
|
2019-06-27 19:39:21 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验回调传回的code
|
2019-08-05 22:05:58 +08:00
|
|
|
* <p>
|
2019-08-06 17:46:51 +08:00
|
|
|
* {@code v1.10.0}版本中改为传入{@code source}和{@code callback},对于不同平台使用不同参数接受code的情况统一做处理
|
2019-06-27 19:39:21 +08:00
|
|
|
*
|
2019-08-05 22:05:58 +08:00
|
|
|
* @param source 当前授权平台
|
|
|
|
|
* @param callback 从第三方授权回调回来时传入的参数集合
|
2019-07-27 07:55:52 +08:00
|
|
|
* @since 1.8.0
|
2019-06-27 19:39:21 +08:00
|
|
|
*/
|
2019-08-05 22:05:58 +08:00
|
|
|
public static void checkCode(AuthSource source, AuthCallback callback) {
|
2020-05-13 00:58:03 +08:00
|
|
|
// 推特平台不支持回调 code 和 state
|
|
|
|
|
if (source == AuthDefaultSource.TWITTER) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-08-05 22:05:58 +08:00
|
|
|
String code = callback.getCode();
|
2019-09-06 22:19:02 +08:00
|
|
|
if (source == AuthDefaultSource.ALIPAY) {
|
2019-08-05 22:05:58 +08:00
|
|
|
code = callback.getAuth_code();
|
2019-09-06 22:19:02 +08:00
|
|
|
} else if (source == AuthDefaultSource.HUAWEI) {
|
2019-08-05 22:05:58 +08:00
|
|
|
code = callback.getAuthorization_code();
|
|
|
|
|
}
|
2019-06-27 19:39:21 +08:00
|
|
|
if (StringUtils.isEmpty(code)) {
|
2019-12-12 14:47:57 +08:00
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_CODE, source);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验回调传回的{@code state},为空或者不存在
|
|
|
|
|
* <p>
|
|
|
|
|
* {@code state}不存在的情况只有两种:
|
|
|
|
|
* 1. {@code state}已使用,被正常清除
|
|
|
|
|
* 2. {@code state}为前端伪造,本身就不存在
|
|
|
|
|
*
|
|
|
|
|
* @param state {@code state}一定不为空
|
2020-03-17 22:57:53 +08:00
|
|
|
* @param source {@code source}当前授权平台
|
2019-12-12 14:47:57 +08:00
|
|
|
* @param authStateCache {@code authStateCache} state缓存实现
|
|
|
|
|
*/
|
|
|
|
|
public static void checkState(String state, AuthSource source, AuthStateCache authStateCache) {
|
2020-05-13 00:58:03 +08:00
|
|
|
// 推特平台不支持回调 code 和 state
|
|
|
|
|
if (source == AuthDefaultSource.TWITTER) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-12-12 14:47:57 +08:00
|
|
|
if (StringUtils.isEmpty(state) || !authStateCache.containsKey(state)) {
|
|
|
|
|
throw new AuthException(AuthResponseStatus.ILLEGAL_STATUS, source);
|
2019-06-27 19:39:21 +08:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-31 17:44:42 +08:00
|
|
|
}
|