【项目实战】前后端分离的SpringCloud项目如何通过AES对称加密算法对登录密码加解密?

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、AES对称加密算法简介

1.1 AES对称加密算法是什么

AESAdvanced Encryption Standard高级加密标准是一种对称加密算法常用于加密数据传输和数据存储。它采用了更高级的替代替代数据加密标准DES的技术并且被认为是目前最安全的对称加密算法。

1.2 AES对称加密算法中基本概念

包括密钥长度、分组密码和循环。

概念解析
密钥SECRET_KEY
密钥长度可以是128、192或256位
分组密码意味着明文被分成若干个组每组再分别加密。
循环循环指加密过程中重复运算的次数。
IV向量可以使用六位十六进制数作为密钥偏移量SECRET_IV

二、前端如何使用AES算法进行加密

用户登录时对登录密码进行加密传输因此需要在前端提供简单的AES对称加密算法实现加密在后端实现解密。
以下是具体的步骤

2.1 定义前端配置文件

在前端配置文件project-ui\src\config\env.js中定义securityKey的值
注意key 和后端网关配置相同这里打包混淆后相对安全。

import {isSandEnv} from "@/util/util";
// 配置编译环境和线上环境之间的切换
const env = process.env
//前端密码密钥必须16位和nacos配置文件base-gateway-dev.yml中的security.encode.key对应
let securityKey = '1234567891234567'
if (env.NODE_ENV == 'development') {
	} else if (env.NODE_ENV == 'production') {
	} else if (env.NODE_ENV == 'test') {
}
export {
  env,
  securityKey
}

2.2 引入前端依赖crypto-js

"dependencies": {
  "crypto-js": "^3.1.9-1",

2.3 编写前端加密方法

import * as CryptoJS from'crypto-js'
/**
 *加密处理
 */
export const encryption = (params) => {
  let {
    data,
    type,
    param,
    key
  } = params
  const result = JSON.parse(JSON.stringify(data))
  if (type === 'Base64') {
    param.forEach(ele => {
      result[ele] = btoa(result[ele])
    })
  } else {
    param.forEach(ele => {
      var data = result[ele]
      key = CryptoJS.enc.Latin1.parse(key)
      var iv = key
      // 加密
      var encrypted = CryptoJS.AES.encrypt(
        data,
        key, {
          iv: iv,
          mode: CryptoJS.mode.CBC,
          padding: CryptoJS.pad.ZeroPadding
        })
      result[ele] = encrypted.toString()
    })
  }
  return result
}

2.4 新建页面JS逻辑

project-ui\src\store\modules\user.js

2.5 引入securityKey字段和encryption方法

import { encryption} from '@/util/util'
import { securityKey } from '@/config/env'

2.6 使用securityKey 字段

  // 根据用户名登录
    LoginByUsername({commit}, userInfo) {
      const user = encryption({
        data: userInfo,
        key: securityKey,
        param: ['password']
      })
      return new Promise((resolve, reject) => {
        loginByUsername(user.username, user.password, user.code, user.randomStr).then(response => {
          const data = response.data
          commit('SET_ACCESS_TOKEN', data.access_token)
          commit('SET_REFRESH_TOKEN', data.refresh_token)
          commit('SET_EXPIRES_IN', data.expires_in)
          commit('CLEAR_LOCK')
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

三、后端如何使用AES算法进行解密

3.1 后端 网关定义迷药

在Nacos上的配置中 base-gateway-dev.yml修改gateway上的配置文件设置好密钥如下

security:
  encode:
    # 前端密码密钥必须16位
    key: '1234567891234567'

3.2 使用hutool提供的工具类进行解密

public class PasswordDecoderFilter extends AbstractGatewayFilterFactory {

	private static final String PASSWORD = "password";
	private static final String KEY_ALGORITHM = "AES";
	@Value("${security.encode.key:1234567812345678}")
	private String encodeKey;
	
	@SneakyThrows
	private static String decryptAES(String data, String pass) {
		AES aes = new AES(Mode.CBC,Padding.NoPadding,
				new SecretKeySpec(pass.getBytes(), KEY_ALGORITHM),
				new IvParameterSpec(pass.getBytes()));
		byte[] result = aes.decrypt(Base64.decode(data.getBytes(StandardCharsets.UTF_8)));
		return new String(result, StandardCharsets.UTF_8);
	}


     @Override
	public GatewayFilter apply(Object config) {
		return (exchange, chain) -> {
			ServerHttpRequest request = exchange.getRequest();

			// 不是登录请求直接向下执行
			if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), SecurityConstants.OAUTH_TOKEN_URL)) {
				return chain.filter(exchange);
			}

			URI uri = exchange.getRequest().getURI();
			String queryParam = uri.getRawQuery();
			Map<String, String> paramMap = HttpUtil.decodeParamMap(queryParam, CharsetUtil.CHARSET_UTF_8);

			String password = paramMap.get(PASSWORD);
			if (StrUtil.isNotBlank(password)) {
				try {
					password = decryptAES(password, encodeKey);
				} catch (Exception e) {
					log.error("密码解密失败:{}", password);
					return Mono.error(e);
				}
				paramMap.put(PASSWORD, password.trim());
			}

			URI newUri = UriComponentsBuilder.fromUri(uri)
				.replaceQuery(HttpUtil.toParams(paramMap))
				.build(true)
				.toUri();

			ServerHttpRequest newRequest = exchange.getRequest().mutate().uri(newUri).build();
			return chain.filter(exchange.mutate().request(newRequest).build());
		};
	}
}

四、参考文档

crypto-js 加密、解密使用方法

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring

“【项目实战】前后端分离的SpringCloud项目如何通过AES对称加密算法对登录密码加解密?” 的相关文章