RSA是一种非对称加密算法。现在,很多登陆表单的密码都采用RSA加密。为登录安全,登录表单输入密码,会加密后传入后台,后台再解密得到原密码,而数据库中存储的一般为原密码MD5加密后的密码,所以后台获取这个原密码后再MD5加密,与数据库中存储的MD5密码比较判断密码是否正确。

一、后端:

1、后端校验接口:

 public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 获取认证的用户名 & 密码
        //前端带入的username
        String username = authentication.getName();
        //前端带入的加密password
        String passwordRsa = authentication.getCredentials().toString();
        //passwordRsa解密后的密码
        String password = "";
        String passwordMd5 = "";
        //RSA解密
        try {
            password = AESUtils.decryptStr(passwordRsa,AESUtils.key);
        } catch (Exception e) {
            throw new UsernameNotFoundException("用户不存在");
        }

        UserDTO userDO = userService.findByUserName(username);
        if (userDO == null) {
            throw new UsernameNotFoundException("用户不存在");
        }

        //判断密码
        try {
            //md5加密
            passwordMd5 = MD5Util.MD5(password);
        } catch (NoSuchAlgorithmException e) {
            throw new UsernameNotFoundException("用户不存在");
        }
        if (!Objects.equals(passwordMd5,userDO.getPassword())){
            throw new BadCredentialsException("密码错误");
        }

        UserDTO userDTO = userService.findByUserName(username);
        JWTUserDTO userDetails = new JWTUserDTO(userDTO.getId(),userDTO.getUserName(),userDTO.getPassword(),
                userDTO.getUserNickName(),null,userDTO.getRoles());
        // 这里设置权限和角色
        Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null,userDetails.getAuthorities());
        return auth;
    }

2、后端util:


import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class AESUtils {

    private static String iv = "HGty&6%4ojyUyhgy";//偏移量字符串必须是16位 当模式是CBC的时候必须设置偏移量
    private static String Algorithm = "AES";
    private static String AlgorithmProvider = "AES/CBC/PKCS5Padding"; //算法/模式/补码方式
    public final static String key="FUjs@17654HGJKKn";

    public static byte[] generatorKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
        keyGenerator.init(256);//默认128,获得无政策权限后可为192或256
        SecretKey secretKey = keyGenerator.generateKey();
        return secretKey.getEncoded();
    }

    public static IvParameterSpec getIv() throws UnsupportedEncodingException {
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
        System.out.println("偏移量:"+byteToHexString(ivParameterSpec.getIV()));
        return ivParameterSpec;
    }

    public static byte[] encrypt(String src, byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
        SecretKey secretKey = new SecretKeySpec(key, Algorithm);
        IvParameterSpec ivParameterSpec = getIv();
        Cipher cipher = Cipher.getInstance(AlgorithmProvider);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
        return cipherBytes;
    }

    public static byte[] decrypt(String src, byte[] key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key, Algorithm);

        IvParameterSpec ivParameterSpec = getIv();
        Cipher cipher = Cipher.getInstance(AlgorithmProvider);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] hexBytes = hexStringToBytes(src);
        byte[] plainBytes = cipher.doFinal(hexBytes);
        return plainBytes;
    }

    /**
     * 解密
     * @param src
     * @param keyStr
     * @return
     * @throws Exception
     */
    public static String decryptStr(String src, String keyStr) throws Exception {

        byte key[] = keyStr.getBytes("utf-8");
        SecretKey secretKey = new SecretKeySpec(key, Algorithm);

        IvParameterSpec ivParameterSpec = getIv();
        Cipher cipher = Cipher.getInstance(AlgorithmProvider);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] hexBytes = hexStringToBytes(src);
        byte[] plainBytes = cipher.doFinal(hexBytes);
        return new String(plainBytes,"UTF-8");
    }


    public static String encrypt(String src, String keyStr) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {

        byte key[] = keyStr.getBytes("utf-8");
        SecretKey secretKey = new SecretKeySpec(key, Algorithm);
        IvParameterSpec ivParameterSpec = getIv();
        Cipher cipher = Cipher.getInstance(AlgorithmProvider);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
        return new String(cipherBytes,"UTF-8");
    }

    public static void main(String args[]){
        try {
            String passwordMd5 = MD5Util.MD5("123456");
            System.out.println("加密后密码:"+passwordMd5);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 将byte转换为16进制字符串
     * @param src
     * @return
     */
    public static String byteToHexString(byte[] src) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xff;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                sb.append("0");
            }
            sb.append(hv);
        }
        return sb.toString();
    }

    /**
     * 将16进制字符串装换为byte数组
     * @param hexString
     * @return
     */
    public static byte[] hexStringToBytes(String hexString) {
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] b = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            b[i] = (byte) (charToByte(hexChars[pos]) << 4 | (charToByte(hexChars[pos + 1]))& 0xff);
        }
        return b;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }


     /*public static void main(String[] args) {
        try {
            // byte key[] = generatorKey();
            System.out.println("FUjs@17654HGJKKn".length());
            // 密钥必须是16的倍数
            byte key[] = "FUjs@17654HGJKKn".getBytes("utf-8");//hexStringToBytes("0123456789ABCDEF");
            String src = "usersrs=111111?sdfjsalkj=1mlkjklasjdfkls?sss=sdfsjlk1123123123?sdd=453456465432165765432221351567897654132";
            System.out.println("密钥:"+byteToHexString(key));
            System.out.println("原字符串:"+src);

            String enc = byteToHexString(encrypt(src, key));
            System.out.println("加密:"+enc);
            System.out.println("解密:"+decryptStr(enc, AESUtils.key));
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/


}

二、前端:

1、登录页:


<template>
<div class="main">
  <el-card class="loginform">
    <el-form >
      <el-row>
        <el-form-item label="用户名">
          <el-col span="6">
            <el-input v-model="user.userName"></el-input>
          </el-col>
        </el-form-item>
      </el-row>

      <el-row>
        <el-form-item label="密码" prop="pass">
			 <label slot="label">密&nbsp;&nbsp;码:</label>
          <el-col span="6">
            <el-input v-model="user.password" type="password" auto-complete="off"></el-input>
          </el-col>
        </el-form-item>
      </el-row>

      <el-row>
        <el-form-item label="验证码" prop="pass">
          <el-col span="4">
            <el-input v-model="user.code" type="code" auto-complete="off"></el-input>
          </el-col>
          <el-col span="2">
            <el-input v-model="code" readonly="readonly" ></el-input>
          </el-col>
        </el-form-item>
      </el-row>

      <el-row >
        <el-col span="6" offset="2">
          <el-form-item size="large">
            <el-button type="primary" @click="login()">登录</el-button>
            <el-button>取消</el-button>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </el-card>
</div>
</template>


<script>
import { login, getCode } from "@/api/login";
import { getToken, setToken, removeToken } from "@/utils/auth";
import { getDAes } from '@/utils/crypto';
export default {
  data() {
    return {
      code: "",
      user: {
        userName: "",
        password: "",
        code: ""
      }
    };
  },

  created() {
    this.getCode();
  },

  methods: {
    getCode() {
      getCode().then(res => {
        this.code = res.data;
      });
    },

    login() {
      this.user.password = getDAes(this.user.password),
      this.$store.dispatch("Login", this.user).then(() => {
        this.$router.push({ path: "/" });
      });
    }
  }
};
</script>


<style>
.main{
	height: 100%;
	width: 100%;
	margin: 0 0;
	background-color: burlywood;
}
.loginform {
	margin-left: 20%;
	margin-right: 20%;
	width: 60%;
   
}
</style>

2、util:

/** @format */
import CryptoJS from 'crypto-js';
import { getToken } from '@/utils/auth';

//加密
function getAesString(data, key, iv) {
  let keyUtf8 = CryptoJS.enc.Hex.parse(key);
  let ivUtf8 = CryptoJS.enc.Hex.parse(iv);
  //这个加密得到 不是字符串
  let encrypted = CryptoJS.AES.encrypt(data, keyUtf8, {
    iv: ivUtf8,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
  return encrypted.ciphertext.toString();
}

export function getDAes(data) {
  const key = '46556a7340313736353448474a4b4b6e';
  const iv = '48477479263625346f6a795579686779';
  let decryptedStr = getAesString(data, key, iv);
  return decryptedStr;
}

export function getSortMd5Sign(params) {
  if (typeof params == 'string') {
    return paramsStrSort(params);
  } else if (typeof params == 'object') {
    var arr = [];
    for (var i in params) {
      arr.push(i + '=' + params[i]);
    }
    return paramsStrSort(arr.join('&'));
  }
}

function paramsStrSort(paramsStr) {
  var urlStr = paramsStr
    .split('&')
    .sort()
    .join('&');
  var newUrl = urlStr + '&token=' + getToken();
  // console.log(newUrl);

  return CryptoJS.MD5(newUrl).toString();
}

三、测试:

如zhangsan密码为123456;

数据库存储:

页面用户名密码分别输入:zhangsan 123456 ,登录成功

Logo

前往低代码交流专区

更多推荐