(1)通常的网络安全有SQL注入,XSS脚本攻击,CRSF伪脚本攻击,DDOS拒绝服务攻击。
(2)SQL注入
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
预防方式:
(3)XSS攻击
XSS攻击的全称是跨站脚本攻击,指的是攻击者在网页中嵌入恶意脚本程序,如。当用户打开该网页时,脚本程序便开始在客户端的浏览器上执行,以盗取客户端cookie,用户名密码,下载执行病毒密码程序,甚至是获取客户端admin权限等。
预防方式:
(4) CRSF攻击
CRSF攻击的全称是跨站请求伪造,是一种对网站的恶意利用,XSS利用的是站点内的信任用户,而CRSF则是通过伪装来自受信任用户的请求来利用受信任的网站。
预防方式:
(5)DDOS拒绝服务攻击
DDOS流量攻击
预防方式:
(1)加密三种方式:不可逆加密、对称加密、不对称加密
(2)不可逆加密
不可逆加密的加密结果没法解密,典型的有:MD5、sha256、HMAC加密
① MD5加密
public class EncUtils {
public static String MD5Enc(String password) {
return DigestUtils.md5Hex(password);
}
}
如果想要加密更深,可以用循环再加密。
public class EncUtils {
public static String MD5Enc(String password) {
for(int i = 0; i < 1024; i++) {
password = DigestUtils.md5Hex(password);
}
return password;
}
}
② sha256加密
public class EncUtils {
public static String sha256Enc(String password) {
for(int i = 0; i < 1024; i++) {
password = DigestUtils.sha256Hex(password);
}
return password;
}
}
③ HMAC加密
(3)对称加密
对称加密算法又称传统加密算法,对称加密跟解密使用的是相同的密钥,加密解密过程:明文->密钥加密->密文,密文->密钥解密->明文
。典型的有:DES(80年代)、3DES、AES(目前常用)(相对不安全)
① DES(Data Encryption Standard)
数据加密标准(现在用的比较少,因为它的加密强度不够,能够暴力破解) 。
② 3DES
原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度。(缺点:要维护3个密钥,大大增加了维护成本) 。
③ AES(Advanced Encryption Standard)
AES加密Demo
AES解密工具 AESUtils 类
public class AESUtils {
//密钥 (需要前端和后端保持一致)
private static final String KEY = "abcdefgabcdefg12";
//算法,ECB定义AES的计算模式,加密算法标准
private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
//aes解密
public static String decr(String content) {
byte[] mes = null;
try {
@SuppressWarnings("restriction")
byte[] base64Content = new BASE64Decoder().decodeBuffer(content);
Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(KEY.getBytes(),"AES"));
mes = new byte[0];
mes = cipher.doFinal(base64Content);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return new String(mes);
}
}
控制层 UsersController 类
@RestController
public class UsersController {
@Resource
private UsersService us;
@GetMapping("login")
public String select(String userName, String userPassword) throws Exception {
System.out.println("AES解密前:" + userPassword);
userPassword = AESUtils.decr(userPassword);
System.out.println("AES解密后:" + userPassword);
System.out.println("userName=" + userName);
//sha256加密
// userPassword = EncUtils.sha256Enc(userPassword);
//MD5加密
userPassword = EncUtils.MD5Enc(userPassword);
String str = null;
Users users = us.selectByUserName(userName);
if(users != null) {
if(users.getUserPassword().equals(userPassword)) {
str = "success";
}else {
str = "error";
}
}else {
str = "账号不存在";
}
return str;
}
}
前端发送请求网页
<body>
<form id="login">
<input name="userName" id="userName"><br>
<input type="password" name="userPassword" id="userPassword"><br>
<input type="button" value="登录" onclick="login()">
</form>
<script type="text/javascript">
function login(){
var userName = $("#userName").val();
var userPassword = $("#userPassword").val();
console.log("AES加密前:" + userPassword);
/* 执行加密方法 */
userPassword = encrypt(userPassword);
console.log("AES加密后:" + userPassword);
$.ajax({
url:"/login",
type:"get",
data:{"userName":userName, "userPassword":userPassword},
success:function(data){
console.log(data);
if(data == "success"){
location.href="success.html";
}else if(data == "error"){
location.href="error.html";
}
}
});
}
/*加密方法(需要先加载aes.js文件)*/
function encrypt(word){
var key = CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return encrypted.toString();
}
/* 解密方法*/
function decrypt(word){
var key = CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}
</script>
</body>
一份比较完整的AES加密工具类
/**
*AES加密解密工具类
*/
public class AESUtils {
//密钥 (需要前端和后端保持一致)
private static final String KEY = "abcdefgabcdefg12";
//算法,ECB定义AES的计算模式,加密算法标准
private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
//aes解密
public static String decr(String content) {
byte[] mes = null;
try {
@SuppressWarnings("restriction")
byte[] base64Content = new BASE64Decoder().decodeBuffer(content);
Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(KEY.getBytes(),"AES"));
mes = new byte[0];
mes = cipher.doFinal(base64Content);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return new String(mes);
}
/**
* aes解密
* @param encrypt 内容
* @return
* @throws Exception
*/
public static String aesDecrypt(String encrypt) {
try {
return aesDecrypt(encrypt, KEY);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
/**
* aes加密
* @param content
* @return
* @throws Exception
*/
public static String aesEncrypt(String content) {
try {
return aesEncrypt(content, KEY);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
/**
* base 64 encode
* @param bytes 待编码的byte[]
* @return 编码后的base 64 code
*/
public static String base64Encode(byte[] bytes){
return Base64.encodeBase64String(bytes);
}
/**
* base 64 decode
* @param base64Code 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception
*/
@SuppressWarnings("restriction")
public static byte[] base64Decode(String base64Code) throws Exception{
return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
}
/**
* AES加密
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的byte[]
* @throws Exception
*/
public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
return cipher.doFinal(content.getBytes("utf-8"));
}
/**
* AES加密为base 64 code
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的base 64 code
* @throws Exception
*/
public static String aesEncrypt(String content, String encryptKey) throws Exception {
return base64Encode(aesEncryptToBytes(content, encryptKey));
}
/**
* AES解密
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
* @throws Exception
*/
public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
// KeyGenerator kgen = KeyGenerator.getInstance("AES");
// kgen.init(128);
Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes);
}
/**
* 将base 64 code AES解密
* @param encryptStr 待解密的base 64 code
* @param decryptKey 解密密钥
* @return 解密后的string
* @throws Exception
*/
public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
}
}
(4)不对称加密
① RSA加密
RSA加密Demo:RSA+时间戳完成登录验证
控制层 UsersController 类
@RestController
public class UsersController {
//记录日志
private static final Logger log = LoggerFactory.getLogger(UsersController.class);
//私钥
private static final String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJX/0JqAPr0mdq9ZN0XqYEVWYApf\r\n" +
"EvoNkmzN0tgQ2CrI0Z8rcmw0CiPH1m1Rp0I/DqiA7XTbqQQMpLLjpUGs11MdLnWvhYqJ04CTK7Bm\r\n" +
"0OwqtIUYxnwPcfGjoOYI2tFB6xWqp6QkmqcF8NAKf8P5kL6L5mXLpI/+6hqlqiFNzM13AgMBAAEC\r\n" +
"gYBgx0ikJpJUH/j7caiD55BtrCkTB/yKcS9EHBgpZ9TQ5fi5paKRxZG1PD5REhnEWELw3R5YA1Gt\r\n" +
"Vyr8cHwzP309GaQVrdrmp5/NnnbuR9Eq7uw9CM+Qovs1Elg77DMh68PNoCbunDsrcOM03+Qm56EL\r\n" +
"ZqilosDyuf+T/uTMkK/OAQJBAM6Cg1c9xrKzcc/vf8c0dnfslSWGJSrA+0vwVJ2Tpb3zO/K4q9OT\r\n" +
"MTlde5QAvDAyBzcebHYcTgtN5wqq5bcLU8ECQQC58lmkx2kn5h9i2OtMFuKgdB8xDMvlOZhrOZ+n\r\n" +
"+Na2qyVr9fO4Zs4koy54t82FdxvVl5YSSifgRVi9Wzy31Y83AkBbndVNGBAV6bxdZsCGjQTd8Wy9\r\n" +
"yASnMhSKvSWc/wrx+X4oEbvRUqTs8UdJAwZ6T0eaMXom8CnDpB0TQ3xEN9dBAkBdGAtvZvKrqheu\r\n" +
"mmF7L734jQqMuRZfxe0cSbY4F2oP/DF5EqMZgEbWquf6QjNgDZje38yfjYbXToC2FLaaZw4TAkAG\r\n" +
"6rBZ4zdmOfkjRRJEpHKZ6ZKlqXW9oe+vqQPUBmBD6wKeBxE2ztdHhhjL4Jit87dxjXOLtP3DsZ0s\r\n" +
"vdKA/Eme";
@Resource
private UsersService us;
@GetMapping("login")
public String select(String userName, String userPassword) throws Exception {
System.out.println("私钥解密前:" + userPassword);
//获取私钥
PrivateKey priKey = RSAUtils.getPrivateKey(privateKey);
userPassword = userPassword.replaceAll(" ", "+");
//解密
userPassword = RSAUtils.decrypt(userPassword, priKey);
System.out.println("私钥解密后:" + userPassword);
//拆分密钥和时间戳
String time = userPassword.substring(userPassword.lastIndexOf("+") + 1);
userPassword = userPassword.substring(0, userPassword.lastIndexOf("+"));
System.out.println("userPassword =" +userPassword);
System.out.println("time =" +time);
long timeBefore = Long.parseLong(time);
//获取当前时间戳
long timeNow = System.currentTimeMillis();
System.out.println(timeBefore +" " + timeNow);
Users users = us.selectByUserName(userName);
String str = null;
if(users != null) {
//MD5加密
userPassword = EncUtils.MD5Enc(userPassword);
if(users.getUserPassword().equals(userPassword)) {
if((timeNow - timeBefore) < 1000) {
str = "success";
}else {
str = "登录超时";
}
}else {
str = "error";
}
}else {
str = "账号不存在";
}
return str;
}
}
前端发送请求代码
<body>
<form id="login">
<input name="userName" id="userName"><br>
<input name="userPassword" id="userPassword"><br>
<input type="button" value="登录" onclick="login()">
</form>
<script type="text/javascript">
function login(){
var userName = $("#userName").val();
var userPassword = $("#userPassword").val();
console.log("公钥加密前:" + userPassword);
/* 定义公钥 */
var publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCV/9CagD69JnavWTdF6mBFVmAKXxL6DZJszdLY" +
"ENgqyNGfK3JsNAojx9ZtUadCPw6ogO1026kEDKSy46VBrNdTHS51r4WKidOAkyuwZtDsKrSFGMZ8" +
"D3Hxo6DmCNrRQesVqqekJJqnBfDQCn/D+ZC+i+Zly6SP/uoapaohTczNdwIDAQAB";
//密码添加时间戳
var time = Date.parse(new Date());
time = time + 1000;
userPassword = userPassword + "+" + time;
console.log("userPassword:" + userPassword);
/* 执行公钥加密 */
var enctype = new JSEncrypt();//创建RSA对象
enctype.setPublicKey(publicKey);//为RSA对象设置公钥
userPassword = enctype.encrypt(userPassword);
console.log("公钥加密后:" + userPassword);
$.ajax({
url:"/login",
type:"get",
data:{"userName":userName, "userPassword":userPassword},
success:function(data){
alert(data);
if(data == "success"){
location.href="success.html";
}else if(data == "error"){
location.href="error.html";
}
}
});
}
}
</script>
</body>
获取公钥私钥字符串
KeyPair keyPair = RSAUtils.getKeyPair();
String publicKey = RSAUtils.getPublicKeyStr(keyPair);
String privateKey = RSAUtils.getPrivateKeyStr(keyPair);
System.out.println(publicKey);
System.out.println(privateKey);
SpringApplication.run(App.class, args);
RSA加密工具类
public class RSAUtils {
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
//获取公钥字符串
public static String getPublicKeyStr(KeyPair keyPair){
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
byte[] by = publicKey.getEncoded();
return Base64.encode(by);
}
//获取私钥字符串
public static String getPrivateKeyStr(KeyPair keyPair){
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
byte[] by = privateKey.getEncoded();
return Base64.encode(by);
}
/**
* 获取密钥对
*
* @return 密钥对
*/
public static KeyPair getKeyPair() {
KeyPairGenerator generator = null;
try {
generator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
generator.initialize(1024);
return generator.generateKeyPair();
}
/**
* 获取私钥
*
* @param privateKey 私钥字符串
* @return
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decode(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
}
/**
* 获取公钥
*
* @param publicKey 公钥字符串
* @return
*/
public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decode(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
}
/**
* RSA加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return
*/
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.getBytes().length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
// 加密后的字符串
return new String(Base64.decode(encryptedData));
}
/**
* RSA解密
*
* @param data 待解密数据
* @param privateKey 私钥
* @return
*/
public static String decrypt(String data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decode(data);
int inputLen = dataBytes.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
return new String(decryptedData, "UTF-8");
}
/**
* 签名
*
* @param data 待签名数据
* @param privateKey 私钥
* @return 签名
*/
public static String sign(String data, PrivateKey privateKey) throws Exception {
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.decode(signature.sign()));
}
/**
* 验签
*
* @param srcData 原始字符串
* @param publicKey 公钥
* @param sign 签名
* @return 是否验签通过
*/
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(Base64.decode(sign.getBytes()));
}
}