mirror of https://gitee.com/topiam/eiam
smallbun
2 years ago
373 changed files with 4778 additions and 6480 deletions
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
|
||||
eiam-authentication-captcha - Employee Identity and Access Management Program |
||||
Copyright © 2020-2023 TopIAM (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.0-beta1</version> |
||||
<relativePath>../pom.xml</relativePath> |
||||
</parent> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<artifactId>eiam-authentication-captcha</artifactId> |
||||
<packaging>jar</packaging> |
||||
<dependencies> |
||||
<!-- common --> |
||||
<dependency> |
||||
<groupId>cn.topiam</groupId> |
||||
<artifactId>eiam-authentication-core</artifactId> |
||||
<version>${project.version}</version> |
||||
</dependency> |
||||
</dependencies> |
||||
</project> |
@ -0,0 +1,121 @@
|
||||
/* |
||||
* eiam-authentication-captcha - Employee Identity and Access Management Program |
||||
* Copyright © 2020-2023 TopIAM (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.captcha.filter; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Objects; |
||||
import java.util.UUID; |
||||
|
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
|
||||
import org.apache.commons.lang3.StringUtils; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.lang.NonNull; |
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; |
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher; |
||||
import org.springframework.web.context.request.RequestContextHolder; |
||||
import org.springframework.web.context.request.ServletRequestAttributes; |
||||
import org.springframework.web.filter.OncePerRequestFilter; |
||||
|
||||
import com.alibaba.fastjson2.JSONObject; |
||||
|
||||
import cn.topiam.employee.authentication.captcha.CaptchaValidator; |
||||
import cn.topiam.employee.common.constants.AuthorizeConstants; |
||||
import cn.topiam.employee.support.result.ApiRestResult; |
||||
import cn.topiam.employee.support.trace.TraceUtils; |
||||
import static cn.topiam.employee.common.constants.AuthorizeConstants.FORM_LOGIN; |
||||
import static cn.topiam.employee.support.constant.EiamConstants.CAPTCHA_CODE_SESSION; |
||||
import static cn.topiam.employee.support.exception.enums.ExceptionStatus.EX000102; |
||||
import static cn.topiam.employee.support.util.HttpResponseUtils.flushResponse; |
||||
|
||||
/** |
||||
* 验证码过滤器 |
||||
* |
||||
* @author TopIAM |
||||
* Created by support@topiam.cn on 2020/10/23 22:34 |
||||
*/ |
||||
public class CaptchaValidatorFilter extends OncePerRequestFilter { |
||||
|
||||
@Override |
||||
protected void doFilterInternal(@NonNull HttpServletRequest request, |
||||
@NonNull HttpServletResponse response, |
||||
@NonNull FilterChain filterChain) throws ServletException, |
||||
IOException { |
||||
if (requiresAuthentication(request)) { |
||||
TraceUtils.put(UUID.randomUUID().toString()); |
||||
boolean validate = captchaValidator.validate(request, response); |
||||
if (!validate) { |
||||
response.setStatus(HttpStatus.BAD_REQUEST.value()); |
||||
flushResponse(response, JSONObject.toJSONString(ApiRestResult.builder() |
||||
.status(EX000102.getCode()).message(EX000102.getMessage()).build())); |
||||
return; |
||||
} |
||||
filterChain.doFilter(request, response); |
||||
TraceUtils.remove(); |
||||
return; |
||||
} |
||||
filterChain.doFilter(request, response); |
||||
} |
||||
|
||||
/** |
||||
* 校验验证码 |
||||
* |
||||
* @param captcha {@link String} |
||||
* @return boolean |
||||
*/ |
||||
public boolean validate(String captcha) { |
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder |
||||
.getRequestAttributes(); |
||||
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); |
||||
String value = String.valueOf(request.getSession().getAttribute(CAPTCHA_CODE_SESSION)); |
||||
return StringUtils.equals(value, captcha); |
||||
} |
||||
|
||||
/** |
||||
* 需要认证 |
||||
* |
||||
* @param request {@link HttpServletRequest} |
||||
* @return {@link Boolean} |
||||
*/ |
||||
protected boolean requiresAuthentication(HttpServletRequest request) { |
||||
OrRequestMatcher requestMatcher = new OrRequestMatcher( |
||||
//登录
|
||||
new AntPathRequestMatcher(FORM_LOGIN, HttpMethod.POST.name()), |
||||
//发送OTP
|
||||
new AntPathRequestMatcher(AuthorizeConstants.LOGIN_OTP_SEND, HttpMethod.POST.name())); |
||||
return requestMatcher.matches(request); |
||||
} |
||||
|
||||
/** |
||||
* CaptchaValidator |
||||
*/ |
||||
private final CaptchaValidator captchaValidator; |
||||
|
||||
/** |
||||
* |
||||
* @param captchaValidator {@link CaptchaValidator} |
||||
*/ |
||||
public CaptchaValidatorFilter(CaptchaValidator captchaValidator) { |
||||
this.captchaValidator = captchaValidator; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,18 @@
|
||||
/* |
||||
* eiam-authentication-captcha - Employee Identity and Access Management Program |
||||
* Copyright © 2020-2023 TopIAM (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.captcha.filter; |
@ -0,0 +1,120 @@
|
||||
/* |
||||
* eiam-authentication-captcha - Employee Identity and Access Management Program |
||||
* Copyright © 2020-2023 TopIAM (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.captcha.geetest; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
|
||||
import org.apache.commons.codec.digest.HmacAlgorithms; |
||||
import org.apache.commons.codec.digest.HmacUtils; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.http.*; |
||||
import org.springframework.util.LinkedMultiValueMap; |
||||
import org.springframework.util.MultiValueMap; |
||||
import org.springframework.web.client.RestTemplate; |
||||
|
||||
import com.alibaba.fastjson2.JSONObject; |
||||
|
||||
import cn.topiam.employee.authentication.captcha.CaptchaValidator; |
||||
import cn.topiam.employee.common.util.RequestUtils; |
||||
|
||||
/** |
||||
* 极速验证 |
||||
* |
||||
* @author TopIAM |
||||
* Created by support@topiam.cn on 2022/8/14 19:11 |
||||
*/ |
||||
public class GeeTestCaptchaValidator implements CaptchaValidator { |
||||
private static final String RESULT = "result"; |
||||
private static final String SUCCESS = "success"; |
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(GeeTestCaptchaValidator.class); |
||||
|
||||
/** |
||||
* 验证 |
||||
* |
||||
* @param request {@link HttpServletRequest} |
||||
* @param response {@link HttpServletResponse} |
||||
* @return {@link Boolean} |
||||
*/ |
||||
@Override |
||||
public boolean validate(HttpServletRequest request, HttpServletResponse response) { |
||||
Map<String, Object> getParams = RequestUtils.getParams(request); |
||||
// 1.初始化极验参数信息
|
||||
String captchaId = config.getCaptchaId(); |
||||
String captchaKey = config.getCaptchaKey(); |
||||
String domain = "https://gcaptcha4.geetest.com"; |
||||
|
||||
// 2.获取用户验证后前端传过来的验证流水号等参数
|
||||
String lotNumber = (String) getParams.get("lot_number"); |
||||
String captchaOutput = (String) getParams.get("captcha_output"); |
||||
String passToken = (String) getParams.get("pass_token"); |
||||
String genTime = (String) getParams.get("gen_time"); |
||||
|
||||
// 3.生成签名
|
||||
// 生成签名使用标准的hmac算法,使用用户当前完成验证的流水号lot_number作为原始消息message,使用客户验证私钥作为key
|
||||
// 采用sha256散列算法将message和key进行单向散列生成最终的签名
|
||||
String signToken = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, captchaKey) |
||||
.hmacHex(lotNumber); |
||||
|
||||
// 4.上传校验参数到极验二次验证接口, 校验用户验证状态
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>(); |
||||
queryParams.add("lot_number", lotNumber); |
||||
queryParams.add("captcha_output", captchaOutput); |
||||
queryParams.add("pass_token", passToken); |
||||
queryParams.add("gen_time", genTime); |
||||
queryParams.add("sign_token", signToken); |
||||
// captcha_id 参数建议放在 url 后面, 方便请求异常时可以在日志中根据id快速定位到异常请求
|
||||
String url = String.format(domain + "/validate" + "?captcha_id=%s", captchaId); |
||||
HttpHeaders headers = new HttpHeaders(); |
||||
HttpMethod method = HttpMethod.POST; |
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); |
||||
JSONObject jsonObject; |
||||
//注意处理接口异常情况,当请求极验二次验证接口异常时做出相应异常处理
|
||||
//保证不会因为接口请求超时或服务未响应而阻碍业务流程
|
||||
try { |
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(queryParams, |
||||
headers); |
||||
ResponseEntity<String> responseEntity = restTemplate.exchange(url, method, |
||||
requestEntity, String.class); |
||||
String resBody = responseEntity.getBody(); |
||||
jsonObject = JSONObject.parseObject(resBody); |
||||
} catch (Exception e) { |
||||
logger.error("验证发生异常: {}", e.getMessage()); |
||||
return false; |
||||
} |
||||
// 5.根据极验返回的用户验证状态, 网站主进行自己的业务逻辑
|
||||
if (SUCCESS.equals(jsonObject.getString(RESULT))) { |
||||
logger.info("验证成功: {}", jsonObject.toJSONString()); |
||||
return true; |
||||
} |
||||
logger.info("验证失败: {}", jsonObject.toJSONString()); |
||||
return true; |
||||
} |
||||
|
||||
private final GeeTestCaptchaProviderConfig config; |
||||
private final RestTemplate restTemplate; |
||||
|
||||
public GeeTestCaptchaValidator(GeeTestCaptchaProviderConfig config, RestTemplate restTemplate) { |
||||
this.config = config; |
||||
this.restTemplate = restTemplate; |
||||
} |
||||
} |
@ -0,0 +1,18 @@
|
||||
/* |
||||
* eiam-authentication-captcha - Employee Identity and Access Management Program |
||||
* Copyright © 2020-2023 TopIAM (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.captcha.geetest; |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue