支付宝认证骨架搭建

pull/33/head
若初 2023-08-19 20:48:11 +08:00 committed by smallbun
parent ad44b7d314
commit d79a22c88d
13 changed files with 327 additions and 15 deletions

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
eiam-authentication-alipay - Employee Identity and Access Management
Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>eiam-authentication</artifactId>
<groupId>cn.topiam</groupId>
<version>1.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eiam-authentication-alipay</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- common -->
<dependency>
<groupId>cn.topiam</groupId>
<artifactId>eiam-authentication-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,34 @@
/*
* eiam-authentication-gitee - Employee Identity and Access Management
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.topiam.employee.authentication.alipay;
import cn.topiam.employee.authentication.common.config.IdentityProviderConfig;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
*
* @author TopIAM
* Created by support@topiam.cn on 2023/8/19 16:09
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class AlipayIdpOAuth2Config extends IdentityProviderConfig {
}

View File

@ -0,0 +1,70 @@
/*
* eiam-authentication-gitee - Employee Identity and Access Management
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.topiam.employee.authentication.alipay.configurer;
import cn.topiam.employee.authentication.alipay.filter.AlipayLoginAuthenticationFilter;
import cn.topiam.employee.authentication.common.service.UserIdpService;
import cn.topiam.employee.common.repository.authentication.IdentityProviderRepository;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
/**
*
*
* @author TopIAM
* Created by support@topiam.cn on 2023/8/19 15:52
*/
public class AlipayAuthenticationConfigurer extends
AbstractAuthenticationFilterConfigurer<HttpSecurity, AlipayAuthenticationConfigurer, AlipayLoginAuthenticationFilter> {
private final IdentityProviderRepository identityProviderRepository;
private final UserIdpService userIdpService;
AlipayAuthenticationConfigurer(IdentityProviderRepository identityProviderRepository,
UserIdpService userIdpService) {
Assert.notNull(identityProviderRepository, "identityProviderRepository must not be null");
Assert.notNull(userIdpService, "userIdpService must not be null");
this.identityProviderRepository = identityProviderRepository;
this.userIdpService = userIdpService;
}
/**
* Create the {@link RequestMatcher} given a loginProcessingUrl
*
* @param loginProcessingUrl creates the {@link RequestMatcher} based upon the
* loginProcessingUrl
* @return the {@link RequestMatcher} to use based upon the loginProcessingUrl
*/
@Override
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
return new AntPathRequestMatcher(loginProcessingUrl);
}
public static AlipayAuthenticationConfigurer alipayOauth(IdentityProviderRepository identityProviderRepository,
UserIdpService userIdpService) {
return new AlipayAuthenticationConfigurer(identityProviderRepository, userIdpService);
}
}

View File

@ -0,0 +1,27 @@
/*
* eiam-authentication-gitee - Employee Identity and Access Management
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.topiam.employee.authentication.alipay.constant;
/**
*
*
* @author TopIAM
* Created by support@topiam.cn on 2023/8/19 15:18
*/
public class AlipayAuthenticationConstants {
}

View File

@ -0,0 +1,41 @@
/*
* eiam-authentication-gitee - Employee Identity and Access Management
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.topiam.employee.authentication.alipay.filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
/**
*
*
* @author TopIAM
* Created by support@topiam.cn on 2023/8/19 17:56
*/
@SuppressWarnings("DuplicatedCode")
public class AlipayAuthorizationRequestRedirectFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
}
}

View File

@ -0,0 +1,56 @@
/*
* eiam-authentication-gitee - Employee Identity and Access Management
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.topiam.employee.authentication.alipay.filter;
import cn.topiam.employee.authentication.common.filter.AbstractIdpAuthenticationProcessingFilter;
import cn.topiam.employee.authentication.common.service.UserIdpService;
import cn.topiam.employee.common.repository.authentication.IdentityProviderRepository;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import java.io.IOException;
/**
*
*
* @author TopIAM
* Created by support@topiam.cn on 2023/8/19 17:58
*/
@SuppressWarnings("DuplicatedCode")
public class AlipayLoginAuthenticationFilter extends AbstractIdpAuthenticationProcessingFilter {
/**
* Creates a new instance
*
* @param defaultFilterProcessesUrl the {@link String}
* @param userIdpService {@link UserIdpService}
* @param identityProviderRepository {@link IdentityProviderRepository}
*/
protected AlipayLoginAuthenticationFilter(String defaultFilterProcessesUrl, UserIdpService userIdpService, IdentityProviderRepository identityProviderRepository) {
super(defaultFilterProcessesUrl, userIdpService, identityProviderRepository);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
return null;
}
}

View File

@ -0,0 +1,18 @@
/*
* eiam-authentication-alipay - Employee Identity and Access Management
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.topiam.employee.authentication.alipay;

View File

@ -75,6 +75,12 @@
<artifactId>eiam-authentication-gitee</artifactId> <artifactId>eiam-authentication-gitee</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<!-- alipay-->
<dependency>
<groupId>cn.topiam</groupId>
<artifactId>eiam-authentication-alipay</artifactId>
<version>${project.version}</version>
</dependency>
<!-- sms--> <!-- sms-->
<dependency> <dependency>
<groupId>cn.topiam</groupId> <groupId>cn.topiam</groupId>

View File

@ -39,7 +39,8 @@ public enum IdentityProviderCategory implements BaseEnum {
IdentityProviderType.QQ_OAUTH, IdentityProviderType.QQ_OAUTH,
IdentityProviderType.WECHAT_QR, IdentityProviderType.WECHAT_QR,
IdentityProviderType.GITEE_OAUTH, IdentityProviderType.GITEE_OAUTH,
IdentityProviderType.GITHUB_OAUTH)), IdentityProviderType.GITHUB_OAUTH,
IdentityProviderType.ALIPAY_OAUTH)),
/** /**
* *
*/ */

View File

@ -106,6 +106,12 @@ public final class IdentityProviderType {
public static final IdentityProviderType GITHUB_OAUTH = new IdentityProviderType( public static final IdentityProviderType GITHUB_OAUTH = new IdentityProviderType(
"github_oauth", "GITHUB认证", "通过GITHUB进行身份认证"); "github_oauth", "GITHUB认证", "通过GITHUB进行身份认证");
/**
*
*/
public static final IdentityProviderType ALIPAY_OAUTH = new IdentityProviderType(
"alipay_oauth", "支付宝认证", "通过支付宝进行身份认证");
private final String value; private final String value;
private final String name; private final String name;
private final String desc; private final String desc;

View File

@ -44,6 +44,7 @@
<module>eiam-authentication-sms</module> <module>eiam-authentication-sms</module>
<module>eiam-authentication-github</module> <module>eiam-authentication-github</module>
<module>eiam-authentication-gitee</module> <module>eiam-authentication-gitee</module>
<module>eiam-authentication-alipay</module>
</modules> </modules>
<dependencies> <dependencies>

View File

@ -58,6 +58,7 @@ import cn.topiam.employee.support.repository.page.domain.QueryDslRequest;
import cn.topiam.employee.support.validation.ValidationUtils; import cn.topiam.employee.support.validation.ValidationUtils;
import jakarta.validation.ConstraintViolationException; import jakarta.validation.ConstraintViolationException;
import static cn.topiam.employee.authentication.common.IdentityProviderType.*; import static cn.topiam.employee.authentication.common.IdentityProviderType.*;
/** /**
@ -113,16 +114,16 @@ public interface IdentityProviderConverter {
} }
IdentityProviderCategory category = IdentityProviderCategory.getType(param.getCategory()); IdentityProviderCategory category = IdentityProviderCategory.getType(param.getCategory());
if (!category.getProviders().stream().map(IdentityProviderType::value).toList() if (!category.getProviders().stream().map(IdentityProviderType::value).toList()
.contains(param.getType())) { .contains(param.getType())) {
throw new TopIamException("认证源类型与认证源提供商不匹配"); throw new TopIamException("认证源类型与认证源提供商不匹配");
} }
try { try {
IdentityProviderConfig identityProviderConfig = getIdentityProviderConfig( IdentityProviderConfig identityProviderConfig = getIdentityProviderConfig(
param.getType(), param.getConfig()); param.getType(), param.getConfig());
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
// 指定序列化输入的类型 // 指定序列化输入的类型
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
//封装数据 //封装数据
IdentityProviderEntity entity = new IdentityProviderEntity(); IdentityProviderEntity entity = new IdentityProviderEntity();
entity.setName(param.getName()); entity.setName(param.getName());
@ -160,15 +161,15 @@ public interface IdentityProviderConverter {
result.setRemark(entity.getRemark()); result.setRemark(entity.getRemark());
//回调地址 //回调地址
result.setRedirectUri(ServerHelp.getPortalPublicBaseUrl() result.setRedirectUri(ServerHelp.getPortalPublicBaseUrl()
+ getIdentityProviderType(entity.getType()).getLoginPathPrefix() + "/" + getIdentityProviderType(entity.getType()).getLoginPathPrefix() + "/"
+ entity.getCode()); + entity.getCode());
try { try {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
// 指定序列化输入的类型 // 指定序列化输入的类型
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
IdentityProviderConfig config = objectMapper.readValue(entity.getConfig(), IdentityProviderConfig config = objectMapper.readValue(entity.getConfig(),
IdentityProviderConfig.class); IdentityProviderConfig.class);
result.setConfig(config); result.setConfig(config);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -188,7 +189,7 @@ public interface IdentityProviderConverter {
QueryDslRequest request = new QueryDslRequest(); QueryDslRequest request = new QueryDslRequest();
QIdentityProviderEntity queryEntity = QIdentityProviderEntity.identityProviderEntity; QIdentityProviderEntity queryEntity = QIdentityProviderEntity.identityProviderEntity;
Predicate predicate = ExpressionUtils.and(queryEntity.isNotNull(), Predicate predicate = ExpressionUtils.and(queryEntity.isNotNull(),
queryEntity.deleted.eq(Boolean.FALSE)); queryEntity.deleted.eq(Boolean.FALSE));
//查询条件 //查询条件
//@formatter:off //@formatter:off
predicate = Objects.isNull(query.getCategory()) ? predicate : ExpressionUtils.and(predicate, queryEntity.category.eq(query.getCategory())); predicate = Objects.isNull(query.getCategory()) ? predicate : ExpressionUtils.and(predicate, queryEntity.category.eq(query.getCategory()));
@ -197,7 +198,7 @@ public interface IdentityProviderConverter {
request.setPredicate(predicate); request.setPredicate(predicate);
//分页条件 //分页条件
request.setPageRequest(QPageRequest.of(pageModel.getCurrent(), pageModel.getPageSize(), request.setPageRequest(QPageRequest.of(pageModel.getCurrent(), pageModel.getPageSize(),
queryEntity.updateTime.desc())); queryEntity.updateTime.desc()));
return request; return request;
} }
@ -212,11 +213,11 @@ public interface IdentityProviderConverter {
return null; return null;
} }
IdentityProviderConfig identityProviderConfig = getIdentityProviderConfig(param.getType(), IdentityProviderConfig identityProviderConfig = getIdentityProviderConfig(param.getType(),
param.getConfig()); param.getConfig());
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
// 指定序列化输入的类型 // 指定序列化输入的类型
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
try { try {
//封装数据 //封装数据
IdentityProviderEntity identityProviderEntity = new IdentityProviderEntity(); IdentityProviderEntity identityProviderEntity = new IdentityProviderEntity();
@ -226,7 +227,7 @@ public interface IdentityProviderConverter {
identityProviderEntity.setRemark(param.getRemark()); identityProviderEntity.setRemark(param.getRemark());
//配置 //配置
identityProviderEntity identityProviderEntity
.setConfig(objectMapper.writeValueAsString(identityProviderConfig)); .setConfig(objectMapper.writeValueAsString(identityProviderConfig));
return identityProviderEntity; return identityProviderEntity;
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -265,9 +266,13 @@ public interface IdentityProviderConverter {
} else if (type.equals(GITHUB_OAUTH.value())) { } else if (type.equals(GITHUB_OAUTH.value())) {
identityProviderConfig = config.to(GithubIdpOauthConfig.class); identityProviderConfig = config.to(GithubIdpOauthConfig.class);
} }
//Gitee //Gitee认证
else if (type.equals(GITEE_OAUTH.value())) { else if (type.equals(GITEE_OAUTH.value())) {
identityProviderConfig = config.to(GiteeIdpOAuth2Config.class); identityProviderConfig = config.to(GiteeIdpOAuth2Config.class);
}
//支付宝认证
else if (type.equals(ALIPAY_OAUTH.value())) {
identityProviderConfig = config.to(GiteeIdpOAuth2Config.class);
} else { } else {
throw new TopIamException("不支持此身份提供商"); throw new TopIamException("不支持此身份提供商");
} }
@ -275,7 +280,7 @@ public interface IdentityProviderConverter {
throw new NullPointerException("提供商配置不能为空"); throw new NullPointerException("提供商配置不能为空");
} }
ValidationUtils.ValidationResult<?> validationResult = ValidationUtils ValidationUtils.ValidationResult<?> validationResult = ValidationUtils
.validateEntity(identityProviderConfig); .validateEntity(identityProviderConfig);
if (validationResult.isHasErrors()) { if (validationResult.isHasErrors()) {
throw new ConstraintViolationException(validationResult.getConstraintViolations()); throw new ConstraintViolationException(validationResult.getConstraintViolations());
} }
@ -325,6 +330,9 @@ public interface IdentityProviderConverter {
if (GITEE_OAUTH.value().equals(type)) { if (GITEE_OAUTH.value().equals(type)) {
return GITEE_OAUTH; return GITEE_OAUTH;
} }
if (ALIPAY_OAUTH.value().equals(type)) {
return ALIPAY_OAUTH;
}
throw new IllegalArgumentException("未知身份提供商类型"); throw new IllegalArgumentException("未知身份提供商类型");
} }
} }

View File

@ -217,6 +217,8 @@ public class PortalSecurityConfiguration extends AbstractSecurityConfiguration
requestMatchers.add(giteeCode.getRequestMatcher()); requestMatchers.add(giteeCode.getRequestMatcher());
httpSecurity.apply(giteeCode); httpSecurity.apply(giteeCode);
//支付宝 todo
//RequestMatcher //RequestMatcher
OrRequestMatcher requestMatcher = new OrRequestMatcher(requestMatchers); OrRequestMatcher requestMatcher = new OrRequestMatcher(requestMatchers);
//社交授权请求重定向匹配器 //社交授权请求重定向匹配器