签名(Signature)认证实现方式-用于请求鉴权

 2023-09-16 阅读 14 评论 0

摘要:常用的请求认证方式有两种: 1、Signature认证 一次性的身份校验方式,常见于不同项目间的api通信 一般形式是通过 AppID/AccessKey/AppSecret 及签名算法针对通信数据生成签名 AccessKey作为公钥,AppSecret作为私钥,AppSecret不能放在网络上传输 接

常用的请求认证方式有两种:

1、Signature认证

一次性的身份校验方式,常见于不同项目间的api通信
一般形式是通过 AppID/AccessKey/AppSecret 及签名算法针对通信数据生成签名
AccessKey作为公钥,AppSecret作为私钥,AppSecret不能放在网络上传输
接口数据推送时,会随带上AppID、AccessKey、Timestamp 及 Signature
在服务端同样留存着一份相同的 AppID/AccessKey/AppSecret 配置
服务端接受到请求后通过AppID对应出匹配的AppSecret,结合相同的签名算法计算签名,并与请求附带的签名做校验
时间戳可以防止恶意用户截取到签名后进行伪装请求,使签名只在一定时间范围内有效,过期后不能再请求
由于每次请求的数据载荷不同,所以一般每次请求都会产生不同的签名.

2、Token认证

本签名方法不支持本签名格式?状态可维持的身份校验方式,常见于第三方服务或APP接口的OAUTH2认证中
一般形式是通过 账号/密码 或 clientId/clientSecret 向认证服务请求Token
服务端Authenticate通过后返回Token,并在一定时间内对Token及相应账号信息进行缓存
后续的接口通信都将通过Token来进行认证
在一段活跃期内, 连续的请求Token是相同

 

本文主要介绍签名认证的主要实现方式

客户端:

(1)封装一个获取时间戳、生成签名的工具类

package com.solin.tools.utils;import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;public class EncryptedUtil {/** HMACSHA256加密签名* Hash-based Message Authentication Code  SHA256* @param sourceStr 加密的源字符串* @param secretAccessKey 密钥*/public static String getSign(String sourceStr,String secretAccessKey) throws Exception{SecretKey secretKey = new SecretKeySpec(secretAccessKey.getBytes(),"HmacSHA256");Mac mac = Mac.getInstance(secretKey.getAlgorithm());mac.init(secretKey);final byte[] hmac = mac.doFinal(sourceStr.getBytes());StringBuilder stringBuilder = new StringBuilder(hmac.length*2);Formatter formatter = new Formatter(stringBuilder);for (byte b :hmac){formatter.format("%02x",b);}formatter.close();return stringBuilder.toString();}/** MD5加密* @param sourceStr 加密的源字符串*/public static String MD5(String sourceStr) {String result = "";try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(sourceStr.getBytes("UTF-8"));byte b[] = md.digest();int i;StringBuffer buf = new StringBuffer("");for (int offset = 0; offset < b.length; offset++) {i = b[offset];if (i < 0)i += 256;if (i < 16)buf.append("0");buf.append(Integer.toHexString(i));}result = buf.toString();} catch (Exception e) {e.printStackTrace();}return result;}/** 时间转换成unix时间戳* @param dateStr 时间字符串*/public static Long getUnixTimestamp(String dateStr){SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");try {Date date = simpleDateFormat.parse(dateStr);return  date.getTime();} catch (ParseException e) {return null;}}

非法请求签名是什么意思,(2)封装一个简单的日期工具类

package com.solin.tools.utils;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*** 日期工具类*/
public class DateUtils {//logprivate final static Logger logger = LoggerFactory.getLogger(DateUtils.class);private DateUtils(){}//Srting转datepublic static Date changeStringToDate(String dateStr) {Date date = new Date();try {date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateStr);} catch (ParseException e) {logger.error(e.getMessage());}return date;}//Srting转date精确到毫秒public static Date changeStringToMillisecondDate(String dateStr) {Date date = new Date();try {date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(dateStr);} catch (ParseException e) {logger.error(e.getMessage());}return date;}//date转String精确到毫秒public static String changeDateToMillisecondString(Date date) {String dateStr = "";try {dateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date);} catch (Exception e) {logger.error(e.getMessage());}return dateStr;}}

 (3)生成时间戳和签名测试

package com.solin.tools;import com.solin.tools.utils.SignResult;/*** 生成签名测试*/
public class SignTest {public static void main(String[] args) throws Exception{ String appId = "123456";String accessKey = "e16188442d8f460696bddf2b";String secretKey = "c0248ad5cced4820835ad54d90ba1fe0";String timestamp = DateUtils.changeDateToMillisecondString(new Date());
// 将timestamp转化为unix时间戳long timestampLong = EncryptedUtil.getUnixTimestamp(timestamp);// 拼接字符串String requestStr = timestampLong + appId + accessKey;// MD5字符串String requestMd5Str = EncryptedUtil.MD5(requestStr);// 生成签名String sign = EncryptedUtil.getSign(requestMd5Str ,secretKey);System.out.println("timestamp ===>>> " + timestamp);System.out.println("sign ===>>> " + sign);}
}

服务端:

(1)时间戳及签名校验工具类


/*** API鉴权工具类* 1、校验时间戳* 2、校验签名 */
public class AppAuthenticationUtils {//log日志private static final Logger logger = LoggerFactory.getLogger(AppAuthenticationUtils.class);//鉴权时间戳范围,单位毫秒public static final long scopeTime = 300000L;/*** API鉴权* @param appId 应用ID* @param accessKey 访问密钥* @param secretKey 签名密钥* @param requestTimestamp 时间戳* @param signature 签名*/public static ResponseStatus checkAuthentication(String appId , String accessKey , String secretKey,String requestTimestamp, String signature)  {long requestUnixTimestamp = EncryptedUtil.getUnixTimestamp(requestTimestamp);// 校验请求时间戳if (!checkRequestTimestamp(requestUnixTimestamp , scopeTime)){return new ResponseStatus(false, "Invalid requestTimestamp ...");}// 校验签名if (!checkSignature(appId, accessKey, secretKey, requestTimestamp,signature)){return new ResponseStatus(false, "Invalid signature...");}return new ResponseStatus(true, "鉴权通过");}/*** 校验签名* @param appId 应用ID* @param accessKey 接口密钥* @param requestTimestamp 时间戳* @param signature 签名*/private static boolean checkSignature(String appId, String accessKey, String secretKey, String requestTimestamp,String signature) {boolean isAuthPass = false;try {long requestUnixTimestamp = EncryptedUtil.getUnixTimestamp(requestTimestamp);String requestMd5Str = EncryptedUtil.MD5(requestUnixTimestamp + appId + accessKey);String sign = EncryptedUtil.getSign(requestMd5Str ,secretKey);if (StringUtils.isNotEmpty(sign) && sign.equals(signature)){isAuthPass = true;}} catch (Exception e) {logger.error("Interface authentication failed ", e);}return isAuthPass;}/*** 判断失效时间* @param requestUnixTimestamp unix时间戳*/private static boolean checkRequestTimestamp(long requestUnixTimestamp  ,long scopeTime){boolean isVaildTimestamp = false;long currentTime = System.currentTimeMillis();long minVaildTime = currentTime - scopeTime;long maxVaildTime = currentTime + scopeTime;if (requestUnixTimestamp >= minVaildTime && requestUnixTimestamp <= maxVaildTime){isVaildTimestamp = true;}return isVaildTimestamp;}}

 

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/67026.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息