split maxkey-authentication-sms

This commit is contained in:
MaxKey
2023-01-03 15:08:07 +08:00
parent 46a57a1a9d
commit f4e36ad0da
23 changed files with 229 additions and 84 deletions

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@@ -0,0 +1,63 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* 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 org.maxkey.autoconfigure;
import org.maxkey.constants.ConstsPersistence;
import org.maxkey.password.onetimepwd.token.RedisOtpTokenStore;
import org.maxkey.password.sms.SmsOtpAuthnService;
import org.maxkey.persistence.redis.RedisConnectionFactory;
import org.maxkey.persistence.service.EmailSendersService;
import org.maxkey.persistence.service.SmsProviderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
@AutoConfiguration
public class SmsAutoConfiguration implements InitializingBean {
private static final Logger _logger =
LoggerFactory.getLogger(SmsAutoConfiguration.class);
@Bean(name = "smsOtpAuthnService")
public SmsOtpAuthnService smsOtpAuthnService(
@Value("${maxkey.server.persistence}") int persistence,
SmsProviderService smsProviderService,
EmailSendersService emailSendersService,
RedisConnectionFactory redisConnFactory) {
SmsOtpAuthnService smsOtpAuthnService =
new SmsOtpAuthnService(smsProviderService,emailSendersService);
if (persistence == ConstsPersistence.REDIS) {
RedisOtpTokenStore redisOptTokenStore = new RedisOtpTokenStore(redisConnFactory);
smsOtpAuthnService.setRedisOptTokenStore(redisOptTokenStore);
}
_logger.debug("SmsOtpAuthnService {} inited." ,
persistence == ConstsPersistence.REDIS ? "Redis" : "InMemory");
return smsOtpAuthnService;
}
@Override
public void afterPropertiesSet() throws Exception {
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* 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 org.maxkey.password.sms;
import java.io.IOException;
import org.maxkey.entity.UserInfo;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.StandardEnvironment;
public class SmsOtpAuthn extends AbstractOtpAuthn {
private static final Logger logger = LoggerFactory.getLogger(SmsOtpAuthn.class);
protected StandardEnvironment properties;
@Override
public boolean produce(UserInfo userInfo) {
String token = this.genToken(userInfo);
// You must add send sms code here
logger.debug("send sms code" + token);
return true;
}
@Override
public boolean validate(UserInfo userInfo, String token) {
return true;
}
public void setProperties(StandardEnvironment properties) {
this.properties = properties;
}
protected void loadProperties() throws IOException {
}
public void initPropertys() {
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* 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 org.maxkey.password.sms;
import java.sql.Types;
import java.util.concurrent.TimeUnit;
import org.maxkey.configuration.EmailConfig;
import org.maxkey.constants.ConstsBoolean;
import org.maxkey.crypto.password.PasswordReciprocal;
import org.maxkey.entity.EmailSenders;
import org.maxkey.entity.SmsProvider;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.maxkey.password.onetimepwd.impl.MailOtpAuthn;
import org.maxkey.password.onetimepwd.token.RedisOtpTokenStore;
import org.maxkey.password.sms.impl.SmsOtpAuthnAliyun;
import org.maxkey.password.sms.impl.SmsOtpAuthnTencentCloud;
import org.maxkey.password.sms.impl.SmsOtpAuthnYunxin;
import org.maxkey.persistence.service.EmailSendersService;
import org.maxkey.persistence.service.SmsProviderService;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
public class SmsOtpAuthnService {
protected static final Cache<String, AbstractOtpAuthn> smsAuthnStore =
Caffeine.newBuilder()
.expireAfterWrite(60, TimeUnit.MINUTES)
.build();
SmsProviderService smsProviderService;
EmailSendersService emailSendersService;
RedisOtpTokenStore redisOptTokenStore;
public SmsOtpAuthnService(SmsProviderService smsProviderService, EmailSendersService emailSendersService) {
this.smsProviderService = smsProviderService;
this.emailSendersService = emailSendersService;
}
public SmsOtpAuthnService(SmsProviderService smsProviderService,EmailSendersService emailSendersService,RedisOtpTokenStore redisOptTokenStore) {
this.smsProviderService = smsProviderService;
this.emailSendersService = emailSendersService;
this.redisOptTokenStore = redisOptTokenStore;
}
public AbstractOtpAuthn getByInstId(String instId) {
AbstractOtpAuthn otpAuthn = smsAuthnStore.getIfPresent(instId);
if(otpAuthn == null) {
SmsProvider smsProvider =
smsProviderService.findOne("where instid = ? ", new Object[]{instId}, new int[]{Types.VARCHAR});
if(smsProvider != null ) {
if(smsProvider.getProvider().equalsIgnoreCase("aliyun")) {
SmsOtpAuthnAliyun aliyun = new SmsOtpAuthnAliyun(
smsProvider.getAppKey(),
smsProvider.getAppSecret(),
smsProvider.getTemplateId(),
smsProvider.getSignName()
);
if(redisOptTokenStore != null) {
aliyun.setOptTokenStore(redisOptTokenStore);
}
otpAuthn = aliyun;
}else if(smsProvider.getProvider().equalsIgnoreCase("tencentcloud")) {
SmsOtpAuthnTencentCloud tencentCloud = new SmsOtpAuthnTencentCloud(
smsProvider.getAppKey(),
smsProvider.getAppSecret(),
smsProvider.getSmsSdkAppId(),
smsProvider.getTemplateId(),
smsProvider.getSignName()
);
if(redisOptTokenStore != null) {
tencentCloud.setOptTokenStore(redisOptTokenStore);
}
otpAuthn = tencentCloud;
}else if(smsProvider.getProvider().equalsIgnoreCase("neteasesms")) {
SmsOtpAuthnYunxin yunxin = new SmsOtpAuthnYunxin(
smsProvider.getAppKey(),
smsProvider.getAppSecret(),
smsProvider.getTemplateId()
);
if(redisOptTokenStore != null) {
yunxin.setOptTokenStore(redisOptTokenStore);
}
otpAuthn = yunxin;
}else if(smsProvider.getProvider().equalsIgnoreCase("email")) {
EmailSenders emailSender =
emailSendersService.findOne("where instid = ? ", new Object[]{instId}, new int[]{Types.VARCHAR});
String credentials = PasswordReciprocal.getInstance().decoder(emailSender.getCredentials());
EmailConfig emailConfig =
new EmailConfig(
emailSender.getAccount(),
credentials,
emailSender.getSmtpHost(),
emailSender.getPort(),
ConstsBoolean.isTrue(emailSender.getSslSwitch()),
emailSender.getSender());
MailOtpAuthn mailOtpAuthn = new MailOtpAuthn(emailConfig);
if(redisOptTokenStore != null) {
mailOtpAuthn.setOptTokenStore(redisOptTokenStore);
}
otpAuthn = mailOtpAuthn;
}
smsAuthnStore.put(instId, otpAuthn);
}
}
return otpAuthn;
}
public void setRedisOptTokenStore(RedisOtpTokenStore redisOptTokenStore) {
this.redisOptTokenStore = redisOptTokenStore;
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* 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 org.maxkey.password.sms.impl;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.maxkey.entity.UserInfo;
import org.maxkey.password.sms.SmsOtpAuthn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 阿里云短信验证.
* @author shimingxy
*
*/
public class SmsOtpAuthnAliyun extends SmsOtpAuthn {
private static final Logger logger = LoggerFactory.getLogger(SmsOtpAuthnAliyun.class);
public SmsOtpAuthnAliyun() {
otpType = OtpTypes.SMS;
}
public SmsOtpAuthnAliyun(String accessKeyId, String accessSecret, String templateCode, String signName) {
otpType = OtpTypes.SMS;
this.accessKeyId = accessKeyId;
this.accessSecret = accessSecret;
this.templateCode = templateCode;
this.signName = signName;
}
//请替换你在管理后台应用下申请的accessKeyId
private String accessKeyId = "94395d754eb55693043f5d6a2b772ef3";
//请替换你在管理后台应用下申请的accessSecret
private String accessSecret = "05d5485357bc";
// 短信模板ID
private String templateCode = "SMS_187590021";
private String signName = "MaxKey";
@Override
public boolean produce(UserInfo userInfo) {
// 手机号
String mobile = userInfo.getMobile();
if (mobile != null && !mobile.equals("")) {
try {
DefaultProfile profile = DefaultProfile.getProfile(
"cn-hangzhou", accessKeyId, accessSecret);
IAcsClient client = new DefaultAcsClient(profile);
String token = this.genToken(userInfo);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("PhoneNumbers", mobile);
request.putQueryParameter("SignName", signName);
request.putQueryParameter("TemplateCode", templateCode);
request.putQueryParameter("TemplateParam", "{\"code\":\"" + token + "\"}");
CommonResponse response = client.getCommonResponse(request);
logger.debug("responseString " + response.getData());
//成功返回
if (response.getData().indexOf("OK") > -1) {
this.optTokenStore.store(
userInfo,
token,
userInfo.getMobile(),
OtpTypes.SMS);
return true;
}
} catch (Exception e) {
logger.error(" produce code error ", e);
}
}
return false;
}
@Override
public boolean validate(UserInfo userInfo, String token) {
return this.optTokenStore.validate(userInfo, token, OtpTypes.SMS, interval);
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessSecret() {
return accessSecret;
}
public void setAccessSecret(String accessSecret) {
this.accessSecret = accessSecret;
}
public String getTemplateCode() {
return templateCode;
}
public void setTemplateCode(String templateCode) {
this.templateCode = templateCode;
}
public String getSignName() {
return signName;
}
public void setSignName(String signName) {
this.signName = signName;
}
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* 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 org.maxkey.password.sms.impl;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
import org.maxkey.entity.UserInfo;
import org.maxkey.password.sms.SmsOtpAuthn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 腾讯云短信验证.
* @author shimingxy
*
*/
public class SmsOtpAuthnTencentCloud extends SmsOtpAuthn {
private static final Logger logger = LoggerFactory.getLogger(SmsOtpAuthnTencentCloud.class);
//
String secretId;
//
String secretKey;
//短信SDKAPPID
String smsSdkAppid;
//短信模板
String templateId;
//签名
String sign;
public SmsOtpAuthnTencentCloud() {
otpType = OtpTypes.SMS;
}
public SmsOtpAuthnTencentCloud(String secretId, String secretKey, String smsSdkAppid, String templateId,
String sign) {
otpType = OtpTypes.SMS;
this.secretId = secretId;
this.secretKey = secretKey;
this.smsSdkAppid = smsSdkAppid;
this.templateId = templateId;
this.sign = sign;
}
@Override
public boolean produce(UserInfo userInfo) {
// 手机号
String mobile = userInfo.getMobile();
if (mobile != null && !mobile.equals("")) {
try {
Credential cred = new Credential(secretId, secretKey);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("sms.tencentcloudapi.com");
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
SmsClient client = new SmsClient(cred, "ap-beijing", clientProfile);
String token = this.genToken(userInfo);
String params = "{\"PhoneNumberSet\":[\"" + mobile + "\"],"
+ "\"TemplateID\":\"" + templateId + "\",\"Sign\":\"" + sign + "\","
+ "\"TemplateParamSet\":[\"" + token + "\",\"" + this.interval + "\"],"
+ "\"SmsSdkAppid\":\"" + smsSdkAppid + "\"}";
SendSmsRequest req = SendSmsRequest.fromJsonString(params, SendSmsRequest.class);
SendSmsResponse resp = client.SendSms(req);
logger.debug("responseString " + SendSmsRequest.toJsonString(resp));
if (resp.getSendStatusSet()[0].getCode().equalsIgnoreCase("Ok")) {
this.optTokenStore.store(
userInfo,
token,
userInfo.getMobile(),
OtpTypes.SMS);
return true;
}
} catch (Exception e) {
logger.error(" produce code error ", e);
}
}
return false;
}
@Override
public boolean validate(UserInfo userInfo, String token) {
return this.optTokenStore.validate(userInfo, token, OtpTypes.SMS, interval);
}
public String getSecretId() {
return secretId;
}
public void setSecretId(String secretId) {
this.secretId = secretId;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getSmsSdkAppid() {
return smsSdkAppid;
}
public void setSmsSdkAppid(String smsSdkAppid) {
this.smsSdkAppid = smsSdkAppid;
}
public String getTemplateId() {
return templateId;
}
public void setTemplateId(String templateId) {
this.templateId = templateId;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
}

View File

@@ -0,0 +1,270 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* 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 org.maxkey.password.sms.impl;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.maxkey.entity.UserInfo;
import org.maxkey.password.sms.SmsOtpAuthn;
import org.maxkey.util.JsonUtils;
import org.maxkey.util.StringGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 网易云信短信验证.
* @author shimingxy
*
*/
public class SmsOtpAuthnYunxin extends SmsOtpAuthn {
private static final Logger logger = LoggerFactory.getLogger(SmsOtpAuthnYunxin.class);
public SmsOtpAuthnYunxin() {
otpType = OtpTypes.SMS;
}
public SmsOtpAuthnYunxin(String appKey, String appSecret, String templateId) {
otpType = OtpTypes.SMS;
this.appKey = appKey;
this.appSecret = appSecret;
this.templateId = templateId;
}
//发送验证码的请求路径URL
private static final String
SERVER_URL = "https://api.netease.im/sms/sendcode.action";
//网易云信分配的账号请替换你在管理后台应用下申请的Appkey
private String
appKey = "94395d754eb55693043f5d6a2b772ef3";
//网易云信分配的密钥请替换你在管理后台应用下申请的appSecret
private String appSecret = "05d5485357bc";
// 短信模板ID
private String templateId = "14860099";
@Override
public boolean produce(UserInfo userInfo) {
HttpPost httpPost = null;
// 手机号
String mobile = userInfo.getMobile();
if (mobile != null && !mobile.equals("")) {
try {
httpPost = new HttpPost(SERVER_URL);
String curTime = String.valueOf((new Date()).getTime() / 1000L);
/*
* 参考计算CheckSum的java代码在上述文档的参数列表中有CheckSum的计算文档示例
*/
// 随机数
String nonce = new StringGenerator(
StringGenerator.DEFAULT_CODE_NUMBER,
6
).randomGenerate();
String checkSum = SmsOtpAuthnYunxinCheckSumBuilder
.getCheckSum(appSecret, nonce, curTime);
logger.debug("AppKey " +appKey+" ,Nonce "+nonce+", CurTime "+curTime+" ,checkSum "+checkSum);
// 设置请求的header
httpPost.addHeader("AppKey", appKey);
httpPost.addHeader("Nonce", nonce);
httpPost.addHeader("CurTime", curTime);
httpPost.addHeader("CheckSum", checkSum);
httpPost.addHeader("Content-Type",
"application/x-www-form-urlencoded;charset=utf-8");
// 设置请求的的参数requestBody参数
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
/*
* 1.如果是模板短信请注意参数mobile是有s的详细参数配置请参考“发送模板短信文档”
* 2.参数格式是jsonArray的格式例如 "['13888888888','13666666666']"
* 3.params是根据你模板里面有几个参数那里面的参数也是jsonArray格式
*/
//https://api.netease.im/sms/sendcode.action
nvps.add(new BasicNameValuePair("templateid", templateId));
nvps.add(new BasicNameValuePair("mobile", userInfo.getMobile()));
nvps.add(new BasicNameValuePair("codeLen", digits + ""));
//authCode 用户自定义验证码
//nvps.add(new BasicNameValuePair("authCode", ""));
//https://api.netease.im/sms/verifycode.action
//nvps.add(new BasicNameValuePair("code", "123456"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
HttpClient httpClient = HttpClientBuilder.create().build();
// 执行请求
HttpResponse response = httpClient.execute(httpPost);
/*
* 1.打印执行结果打印结果一般会200、315、403、404、413、414、500
* 2.具体的code有问题的可以参考官网的Code状态表
*/
//{"code":200,"msg":"1","obj":"740673"}
String responseString = EntityUtils.toString(response.getEntity(), "utf-8");
//String responseString = "{\"code\":200,\"msg\":\"1\",\"obj\":\"740673\"}";
logger.debug("responseString " + responseString);
YunxinSms yunxinSms =
JsonUtils.gsonStringToObject(responseString,YunxinSms.class);
logger.debug("responseEntity code " + yunxinSms.getObj());
nonce = yunxinSms.getObj() == null ?nonce:yunxinSms.getObj();
logger.debug("nonce " + nonce);
this.optTokenStore.store(
userInfo,
nonce,
userInfo.getMobile(),
OtpTypes.SMS);
return true;
} catch (Exception e) {
logger.error(" produce code error ", e);
} finally {
if (httpPost != null) {
httpPost.releaseConnection();
}
}
}
return false;
}
@Override
public boolean validate(UserInfo userInfo, String token) {
return this.optTokenStore.validate(userInfo, token, OtpTypes.SMS, interval);
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
public String getTemplateId() {
return templateId;
}
public void setTemplateId(String templateId) {
this.templateId = templateId;
}
public class YunxinSms {
int code;
String msg;
String obj;
public YunxinSms() {
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getObj() {
return obj;
}
public void setObj(String obj) {
this.obj = obj;
}
}
/**
* main.
* @param args String
* @throws Exception throws
*/
public static void main(String[] args) throws Exception {
String nonce = new StringGenerator(
StringGenerator.DEFAULT_CODE_NUMBER,
6
).randomGenerate();
System.out.println(nonce);
String mapJson = "{\"code\":200,\"msg\":\"1\",\"obj\":\"740673\"}";
YunxinSms yunxinSms = JsonUtils.gsonStringToObject(mapJson,YunxinSms.class);
System.out.println("code " + yunxinSms.getObj());
}
}
class SmsOtpAuthnYunxinCheckSumBuilder {
// 计算并获取CheckSum
public static String getCheckSum(String appSecret, String nonce, String curTime) {
return encode("sha1", appSecret + nonce + curTime);
}
// 计算并获取md5值
public static String getMD5(String requestBody) {
return encode("md5", requestBody);
}
private static String encode(String algorithm, String value) {
if (value == null) {
return null;
}
try {
MessageDigest messageDigest
= MessageDigest.getInstance(algorithm);
messageDigest.update(value.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
}