文章目录

  • 前言
  • 一、通信模型
  • 二、代码实现
    • 1.引入jar包
    • 2.构建密钥
    • 3.消息接收方
    • 4.消息发送方
  • 总结

前言

HmacSHA256是带有密钥的消息摘要算法(详细介绍:java实现消息摘要算法),经常用于验证消息完整性。本篇通过简化的接口调用,阐述该算法在项目中的使用


一、通信模型

二、代码实现

工程搭建参照上篇

1.引入jar包

 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.10</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.68</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>

2.构建密钥

构建密钥,并且通信双方都保存该密钥

public class HmacUtil {public static void main(String[] args) throws NoSuchAlgorithmException {byte[] bytes = initHmacSHA256Key();System.out.println(Hex.encodeHexString(bytes));}/*** 初始化密钥** @return 密钥* @throws NoSuchAlgorithmException NoSuchAlgorithmException*/public static byte[] initHmacSHA256Key() throws NoSuchAlgorithmException {KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacSHA256");SecretKey secretKey = keyGenerator.generateKey();return secretKey.getEncoded();}private static byte[] hmacSHA256(byte[] key, String valueToDigest) throws Exception {// 还原密钥SecretKeySpec sk = new SecretKeySpec(key, "HmacSHA256");Mac mac = Mac.getInstance(sk.getAlgorithm());mac.init(sk);return mac.doFinal(valueToDigest.getBytes(StandardCharsets.UTF_8));}public static String hmacSHA256Str(byte[] key, String valueToDigest) throws Exception {// 还原密钥byte[] bytes = hmacSHA256(key, valueToDigest);return Hex.encodeHexString(bytes);}public static String hmacSHA256Str(String key, String valueToDigest) throws Exception {// 还原密钥byte[] bytes = hmacSHA256(Hex.decodeHex(key), valueToDigest);return Hex.encodeHexString(bytes);}
}

3.消息接收方

增加过滤器进行校验,其中digest.workKey放到配置文件workKey.properties

@PropertySource("classpath:workKey.properties")
@WebFilter(filterName = "digestAuthFilter", urlPatterns = "/*")
public class MsgDigestAuthFilter implements Filter {@Value("${digest.workKey}")private String digestWorkKey;private byte[] key;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {try {// 这里简单地对密钥进行转码,实际上要进行解密key = Hex.decodeHex(digestWorkKey);} catch (DecoderException e) {e.printStackTrace();}}@Overridepublic void doFilter(ServletRequest req, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 这里对摘要进行校验HttpServletRequest request = (HttpServletRequest) req;String jsonStr = getJsonStr(request);String head = request.getHeader("Authorization");if (checkHeadAuthorization(head, jsonStr)) {filterChain.doFilter(request, servletResponse);return;}// log,抛自定义异常throw new ServletException("No Permission!");}private boolean checkHeadAuthorization(String head, String body) {if (StringUtils.isEmpty(head)) {//logreturn false;}Map<String, String> authValue = getAuthValue(head);String response = authValue.get("response");if (StringUtils.isEmpty(response)) {return false;}try {String currentResp = HmacUtil.hmacSHA256Str(key, body);return response.equals(currentResp);} catch (Exception e) {e.printStackTrace();return false;}}private String getJsonStr(HttpServletRequest request) {StringBuilder builder = new StringBuilder();try (BufferedReader reader = request.getReader()) {String line;while ((line = reader.readLine()) != null) {builder.append(line);}} catch (IOException e) {e.printStackTrace();}return builder.toString();}/*** 这里根据自己定义的规则获取鉴权信息,仅供参考** @param authorization authorization* @return Map<String, String>*/private Map<String, String> getAuthValue(String authorization) {Map<String, String> map = new HashMap<String, String>();String[] token = authorization.split(",");for (String each : token) {String[] subToken = each.split("=");if (subToken.length > 1) {String key = subToken[0].trim();String[] keyArray = key.split(" ");if (keyArray.length > 1) {key = keyArray[keyArray.length - 1];}map.put(key, subToken[1]);}}return map;}
}

过滤器生效

@SpringBootApplication
@ServletComponentScan(basePackages = "com.filter")
public class MyServerSpringBootApplication {public static void main(String[] args) {SpringApplication.run(MyServerSpringBootApplication.class, args);}
}

controller层

@RestController
public class WebController {@PostMapping("digest")public String testDigest() {System.out.println("ok");return "ok";}
}

4.消息发送方

实际上密钥应加密放到配置文件中,这里省略直接放到代码里面

@RunWith(SpringRunner.class)
public class Client {private String key = "d79742ea7ec2543963620a128cfef8acb45492fec3c035b0070b7fcc485068d3";@Testpublic void test() throws Exception {String url = "http://localhost:56000/digest";HttpPost httpPost = new HttpPost(url);httpPost.setHeader("Content-Type","application/json;charset=utf-8");String content = JSON.toJSONString(new RequestInfo("helloWorld"));StringEntity entity = new StringEntity(content, ContentType.APPLICATION_JSON);httpPost.setEntity(entity);String digest = HmacUtil.hmacSHA256Str(key, content);StringBuilder builder = new StringBuilder();builder.append("Digest appID=").append("yourAppId")// 这里设置服务器标识.append(",").append("response=").append(digest);httpPost.setHeader("Authorization", builder.toString());CloseableHttpResponse response = HttpClients.createDefault().execute(httpPost);System.out.println(response.getStatusLine().getStatusCode());}
}

发送实体类

@Data
@AllArgsConstructor
public class RequestInfo {private String msg;
}

总结

HmacSHA算法带有密钥,除了可以验证消息的完整性,还起到了认证的作用。笔者在上述演示中没有对发送的消息进行加密,实际通信如果涉及到敏感数据或个人信息,应当采用https请求或者加密传输。

HmacSHA256算法实现消息认证相关推荐

  1. 【密码学原理】消息认证概述,Hash和MAC

    网络通信环境下可能存在的攻击: 泄密:将消息透露给没有合法密钥的第三方 传输分析:分析通信双方的通信模式,连接频率.持续时间.消息数量和长度 伪装:向网络中插入消息 内容修改:对消息内容修改 顺序修改 ...

  2. JAVA加密解密之消息认证码算法(Message Authentication Code,MAC)

    消息认证码算法简介 在密码学中,消息认证码(英语:Message authentication code,缩写为MAC),又译为消息鉴别码.文件消息认证码.讯息鉴别码.信息认证码,是经过特定算法后产生 ...

  3. HMAC(1)消息认证码MAC算法

    1. 定义 MAC(Message Authentication Code) 算法是以消息本身和密钥作为输入,经过一系列计算产生一个消息哈希的算法,用来保证消息的数据完整性和消息的数据源认证. 2. ...

  4. 【转】HMAC哈希消息认证码及算法原理

    HMAC算法原理 HMAC算法是一种基于密钥的报文完整性的验证方法 ,其安全性是建立在Hash加密算法基础上的.它要求通信双方共享密钥.约定算法.对报文进行Hash运算,形成固定长度的认证码.通信双方 ...

  5. 加解密算法、消息摘要、消息认证技术、数字签名与公钥证书

    本文讲解对称加密.非对称加密.消息摘要.MAC.数字签名.公钥证书的用途.不足和解决的问题. 0.概述 当发送方A向接收方B发送数据时,需要考虑的问题有: 1.数据的安全性. 2.数据的完整性,即数据 ...

  6. 消息认证之SHA散列算法族

    消息认证--安全散列算法SHA(Secure Hash Algorithm) 一. 消息认证 对要传递的消息进行加密有两个目的,其一是防止消息被消息发送者和消息接收者之外的第三者窃听(被动攻击),在之 ...

  7. java mac 加密_Algorithm:Java加密解密之MAC(消息认证码)

    MD5 消息摘要(数字摘要) 它是把一个文本/文件 通过摘要函数(hash函数)计算出一个结果.然后把文本/文件和摘要结果一同发给接受者 接受者接收到文件之后,也进行摘要,把两个摘要结果进行对比.如果 ...

  8. 信息安全——消息认证与数字签名

    消息认证和数字签名是为防止以下情况: (1)伪造:从假冒信源向网络插入消息. (2)内容修改:消息内容被插入.删除.变换等. (3)顺序修改:重组消息序列. (4)时间修改:消息延迟或重放. (5)否 ...

  9. 密码学入门(6):消息认证码

    密码学入门(6):消息认证码 文章目录 密码学入门(6):消息认证码 什么是消息认证码? 消息认证码的实现方式 HMAC 认证加密 重放攻击 防御重放攻击的方式 消息认证码无法解决的问题 参考 上次讲 ...

  10. 浅浅学习一下消息认证码MAC(Message Authentication Code)

    1.MAC这玩意是什么? 提起这个MAC我就不得不说一下消息摘要. 什么是消息摘要? 消息摘要是把任意长度的输入揉和而产生长度固定的伪随机输出的算法.消息摘要的主要特点有: ①无论输入的消息有多长,计 ...

最新文章

  1. iOS ALAsset的选取和存储
  2. python学到什么程度可以做兼职-Python学到什么程度就可以找工作?
  3. C/C++之Gcc常用参数
  4. Pwn_9 作业讲解
  5. 关于for循环中的变量int i 如果跳出了这个for循环后,i的值是继续保留还是被释放掉了
  6. 用node.js读写文件
  7. 【perl】simpleHTTP
  8. sql语句优化之一:尽量使用索引避免全表扫描
  9. 北京黑龙江商会成立纪实(2)
  10. 什么使软件程序员成为专业人士?
  11. 报表填报时,如何实现多个单元格绑定一个字段?
  12. Struts入门经验(二)
  13. String 类 的 使用
  14. 网页源代码保护(禁止右键、复制、另存为、查看源文件)
  15. 如何为搭建的网站配置自己的域名 1-2
  16. 天猫精灵python开发_天猫精灵X1智能音箱使用感想
  17. 2021年西式面点师(初级)考试题库及西式面点师(初级)考试试题
  18. meta分析 1. Risk Ratio
  19. ncverilog脚本_Ncverilog 常用命令使用详解 | 学步园
  20. java hadoop mahout_hadoop 之Mahout 数据挖掘

热门文章

  1. 北大学子求职经历与建议(IT类) 收藏
  2. Spring BeanFactory和FactoryBean的区别
  3. spring security执行原理流程
  4. 小程序wx.showActionSheet 调起转发、分享
  5. 不可不知的socket和TCP连接过程
  6. 中国网络空间安全协会成立 永信至诚等200家单位共建网络安全
  7. 怎么用几何画板作一些简单的图形
  8. POJ 3415 Common Substrings (后缀数组,长度不小于k的公共子串的个数)
  9. 旅游后台管理系列——SSM框架Web表现层
  10. [Android] 软件中选择文件夹功能