数据安全
数据安全有对立的两方面的含义:一是数据本身的安全,主要是指采用现代密码算法对数据进行主动保护,如数据保密、数据完整性、双向强身份认证等,二是数据防护的安全,主要是采用现代信息存储手段对数据进行主动防护,如通过磁盘阵列、数据备份、异地容灾等手段保证数据的安全,数据安全是一种主动的包含措施,数据本身的安全必须基于可靠的加密算法与安全体系,主要是有对称算法与公开密钥密码体系两种。
数据加密(Java)
数据分为:静态数据和动态数据。加密方式也有所不同。保护方法可分为:加密、签名、令牌化(假名化和匿名化)、数据屏蔽和透明文件加密。对数据的保护,要依据数据的类型,以及业务场景具体分析,不能一概用数据加密来对数据进行保护。例如:金融公司就无法对财务数据进行加密,因为一旦加密后,就无法做模糊查询和比值查询。但财务数据也很重要。因此要站在数据保护的视角对数据进行处理,而不能用数据加密的方法进行处理。另外,此问题在其他作者的回答中,提到了DLP(数据防泄漏),本人认为略有不妥。DLP是一种保护手段,只是对数据进行黑白名单处理或对文件进行标签处理,最终管控的是数据或文件在通讯层上的流转,只能称为保护手段,而并不是一种加密方法。
Java常见的加密方式
为什么数据要加密呢?
所以在互联网当今,数据安全是至关重要的,对于敏感数据,加密请求参数,各种签名验证也是非常重要的,作为开发人员更需要有安全意识,比如对外接口设置,请求在网关层进行相应的隔离!
数据加密方式 (支付宝加密)
····对称加密原理
对称加密:对称加密加密和解密使用同一个密钥。 加密过程如下:
加密:原文 + 密匙 = 密文
解密:密文 - 密匙 = 原文
前端请求参数
后端参数处理
·····什么是非对称加密?
非对称加密算法的密匙是通过一系列算法获取到的一长串随机数,通常随机数的长度越长,加密信息越安全。通过私钥经过一系列算法是可以推导出公钥的,也就是说,公钥是基于私钥而存在的。但是无法通过公钥反向推倒出私钥,这个过程的单向的。
信息安全过程中,接收方只需要保管好自己的私钥不泄露即可。
同样,当接收方向发送方发送消息时,接收方将密文通过原发送方的公钥进行加密
对称加密:
优点:算法简单,加密解密容易,效率高,执行快。
缺点:相对来说不算特别安全,只有一把钥匙,密文如果被拦截,且密钥也被劫持,那么,信息很容易被破译。
非对称加密:
优点:安全,即使密文被拦截、公钥被获取,但是无法获取到私钥,也就无法破译密文。作为接收方,务必要保管好自己的密钥。
缺点:加密算法及其复杂,安全性依赖算法与密钥,而且加密和解密效率很低。
什么是数字证书?
数字证书有点类似于我们的居民身份证,只是数字证书是基于互联网通信的,用于标记通信双方身份的一种方式。数字证书是由权威机构Certificate
Authority发行的,又称之为证书授权,简称为:CA。人们在网上可以根据它来识别对方身份信息。数字证书绑定了公钥及其持有者的真实身份,它类似于现实生活中的居民身份证,所不同的是数字证书不再是纸质的证照,而是一段含有证书持有者身份信息并经过认证中心审核签发的电子数据,广泛用在电子商务和移动互联网中
四:什么是数字签名?
数字签名是指将摘要信息使用接收者的公钥进行加密,与密文一起发送给接收者。接收者使用自己的私钥对摘要信息进行解密,然后使用Hash函数对收到的密文产生一个摘要信息,然后将摘要信息与发送着传输过来解密后的摘要信息对比是否一致。如果一致,则表明数据信息没有被篡改。
也就是说,数字签名能够验证收到的信息的完整性,避免中途信息被劫持篡改或丢失。对方可以根据数字签名来判断获取到的数据信息时候是最原始的数据
签名JWT(登录时token 或者按需生成签名信息)
对于请求,我们需要一下用户信息,如果能按照一定的规则生成,并且加密用户信息,放在请求头,每次请求都会有携带,后端(服务层可以去解析用户信息,可以极大提安全性),并且在gateWay(网关层面对请求限制),必须携带用户信息,这也是符合当今的一种安全信息设置!
JWT原理
SON Web Token (or
JWT)只是一个包含某种意义数据的JSON串。它最重要的特性就是,为了确认它是否有效,我们只需要看JWT本身的内容,而不需要借助于第三方服务或者在多个请求之间将其保存在内存中-这是因为它本身携带了信息验证码MAC(Message
Authentication Code)。
一个JWT包含3个部分:头部Header,数据Payload,签名Signature。让我们逐个来了解一下,先从Payload开始吧。
JWT Payload看起来是怎样的呢?
Payload只是一个普通的Javascript
对象。对于payload的内容,JWT是没有任何限制的,但必须注意的是,JWT是没有加密的。因此,任何放在token里面的信息,如果被截获了,对任何人别人是可读的。因此,我们不应该在Payload里面存放任何黑客可以利用的用户信息。
JWT Header – 为什么是必须的?
Payload的内容在接收者端是通过签名(Signature)来校验的。不过存在多种类型的签名,因此,接收者需要知道使用的是哪种类型的签名。
这种关于token本身的元数据信息存放在另外的Javascript对象里面,并随着Payload一起发送给客户。这个独立的对象就是一个JSON对象,叫JWT
Header,它也是普通的Javascript对象,在这里面我们可以看到签名类型信息,比如RS256。
JWT生成token长啥样呢?(一串字符,三部分组成,“.”隔开 )
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
(Header.Payload.Signature)(原理性的东西还很多,可自己去了解)
package com.taoci.taoci.stu.utils;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
/**
* @Description: 签名JWT工具包
* @Author: liaocongcong
* @Date: 2021/10/17 15:48
*/
public class JwtUtils {
private static final long EXPIRE = 60 * 1000; //过期时间
public static final SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);//密钥,动态生成的密钥
/**
* 生成token
*
* @param claims 要传送消息map
* @return
*/
public static String generate(Map<String, Object> claims) {
Date nowDate = new Date();
//过期时间,设定为一分钟
Date expireDate = new Date(System.currentTimeMillis() + EXPIRE);
//头部信息,可有可无
Map<String, Object> header = new HashMap<>(2);
header.put("typ", "jwt");
//更强的密钥,JDK11起才能用
// KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256);
// PrivateKey key1 = keyPair.getPrivate(); // 私钥
//PublicKey key2 = keyPair.getPublic(); //公钥
return Jwts.builder().setHeader(header)
// .setSubject("weimi")//主题
// .setIssuer("weimi") //发送方
.setClaims(claims) //自定义claims
.setIssuedAt(nowDate)//当前时间
.setExpiration(expireDate) //过期时间
.signWith(key)//签名算法和key
.compact();
}
/**
* 生成token
*
* @param header 传入头部信息map
* @param claims 要传送消息map
* @return
*/
public static String generate(Map<String, Object> header, Map<String, Object> claims) {
Date nowDate = new Date();
//过期时间,设定为一分钟
Date expireDate = new Date(System.currentTimeMillis() + EXPIRE);
return Jwts.builder().setHeader(header)
// .setSubject("weimi")//主题
// .setIssuer("weimi") //发送方
.setClaims(claims) //自定义claims
.setIssuedAt(nowDate)//当前时间
.setExpiration(expireDate) //过期时间
.signWith(key)//签名算法和key
.compact();
}
/**
* 校验是不是jwt签名
*
* @param token
* @return
*/
public static boolean isSigned(String token) {
return Jwts.parser()
.setSigningKey(key)
.isSigned(token);
}
/**
* 校验签名是否正确
*
* @param token
* @return
*/
public static boolean verify(String token) {
try {
Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token);
return true;
} catch (JwtException e) {
System.out.println(e.getMessage());
return false;
}
}
/**
* 获取payload 部分内容(即要传的信息)
* 使用方法:如获取userId:getClaim(token).get("userId");
*
* @param token
* @return
*/
public static Claims getClaim(String token) {
Claims claims = null;
try {
claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
e.printStackTrace();
}
return claims;
}
/**
* 获取头部信息map
* 使用方法 : getHeader(token).get("alg");
*
* @param token
* @return
*/
public static JwsHeader getHeader(String token) {
JwsHeader header = null;
try {
header = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token)
.getHeader();
} catch (Exception e) {
e.printStackTrace();
}
return header;
}
/**
* 获取jwt发布时间
*/
public static Date getIssuedAt(String token) {
return getClaim(token).getIssuedAt();
}
/**
* 获取jwt失效时间
*/
public static Date getExpiration(String token) {
return getClaim(token).getExpiration();
}
/**
* 验证token是否失效
*
* @param token
* @return true:过期 false:没过期
*/
public static boolean isExpired(String token) {
try {
final Date expiration = getExpiration(token);
return expiration.before(new Date());
} catch (ExpiredJwtException expiredJwtException) {
return true;
}
}
/**
* 直接Base64解密获取header内容
*
* @param token
* @return
*/
public static String getHeaderByBase64(String token) {
String header = null;
if (isSigned(token)) {
try {
byte[] header_byte = Base64.getDecoder().decode(token.split("\\.")[0]);
header = new String(header_byte);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
return header;
}
/**
* 直接Base64解密获取payload内容
*
* @param token
* @return
*/
public static String getPayloadByBase64(String token) {
String payload = null;
if (isSigned(token)) {
try {
byte[] payload_byte = Base64.getDecoder().decode(token.split("\\.")[1]);
payload = new String(payload_byte);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
return payload;
}
public static void main(String[] args) {
//用户自定义信息claims
Map<String, Object> map = new HashMap<>();
map.put("userId", "test122");
String token = "eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50S" +
"WQiOjE0NDk5ODY5OTY1OTk4MDM5MDQsImNyZWF0ZVRpbWUiOjE2MzQ1Mzg5MDYwMDAsInVzZXJu" +
"YW1lIjoiYWRtaW4iLCJpYXQiOjE2MzQ1NDIwNTQsImV4cCI6MTYzNDU0MjE" +
"xNH0.xBzAv08zBi31GXgPnc81t9YgJYiqe1wk6GKqGXoRAVw";
System.out.println(token);
System.out.println("claim:" + getClaim(token).get("userId"));
System.out.println("header:" + getHeader(token));
// System.out.println(getIssuedAt(token));
Claims claims = getClaim(token);
// System.out.println(getHeaderByBase64(token));
System.out.println(getPayloadByBase64(token));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
System.out.println("签发时间:" + sdf.format(claims.getIssuedAt()));
System.out.println("过期时间:" + sdf.format(claims.getExpiration()));
System.out.println("当前时间:" + sdf.format(new Date()));
}
}
感觉还有很多,上班中,撤了,老大要来了,补上上周的@lcc