Maison  >  Article  >  Java  >  Comment obtenir une connexion sécurisée avec le double cryptage Java MD5

Comment obtenir une connexion sécurisée avec le double cryptage Java MD5

WBOY
WBOYavant
2023-05-17 17:31:351328parcourir

Un : Introduction du problème

Décrypter le mot de passe stocké dans la base de données :

Comment obtenir une connexion sécurisée avec le double cryptage Java MD5

Comment obtenir une connexion sécurisée avec le double cryptage Java MD5

Vous pouvez voir que mon mot de passe a été déchiffré avec succès, ce qui m'a surpris, car nous savons tous que l'algorithme MD5 est irréversible car il s'agit d'une fonction de hachage et utilise l'algorithme de hachage. Pendant le processus de calcul, une partie des informations d'origine est perdue. Alors pourquoi mon mot de passe peut-il être déchiffré sur le site Web ?

Après quelques recherches, j'ai découvert que le principe de décryptage de l'outil de décryptage en ligne est très simple. Le principe est de collecter des mots de passe simples couramment utilisés par les utilisateurs pour former un dictionnaire de mots de passe, puis de crypter les mots de passe dans le dictionnaire avec MD5 et de les stocker. Dans ce que l'on appelle lors du « déchiffrement », comparez le texte chiffré du cryptage du mot de passe de l'utilisateur réel avec le mot de passe stocké. Si le texte chiffré existe dans le dictionnaire, il peut être « déchiffré ». Par conséquent, utiliser simplement MD5 pour crypter les mots de passe des utilisateurs n'est pas sûr. Lorsque nous définissons des mots de passe, nous avons généralement une détection de complexité. Par exemple, le mot de passe doit contenir des chiffres anglais, etc., uniquement pour des raisons de sécurité.

Après avoir connu le principe de décryptage, nous essayons un mot de passe plus complexe pour voir s'il peut être "déchiffré". Tout d'abord, cryptons le mot de passe "qweasd666":

Comment obtenir une connexion sécurisée avec le double cryptage Java MD5

Après le cryptage, nous sélectionnons le texte chiffré en minuscules à 32 chiffres pour décryptage.Opération :

Comment obtenir une connexion sécurisée avec le double cryptage Java MD5

L'échec du décryptage indique que le principe est de collecter les textes chiffrés couramment utilisés pour la correspondance et le craquage. Puisque le mot de passe "qweasd666" ne peut pas être déchiffré, il devrait être sûr et vous pouvez tous utiliser ce mot de passe (doge).

Pour en revenir au sujet, ce site Web a réussi à déchiffrer mon mot de passe soigneusement défini, ce qui m'a donné un sentiment d'insécurité et j'ai senti que je perdais la face. Je devais améliorer mon niveau de sécurité de connexion.

En plus de l'opération de décryptage mentionnée ci-dessus, un autre gros problème est que lorsque le front-end transmet des données, http utilise la transmission en texte brut. Si le paquet de données de transmission est intercepté, quel que soit le nombre d'algorithmes de cryptage dont dispose votre back-end. Complexe, votre mot de passe sera connu des autres.

Deux : Solution

2.1 : Premier cryptage

Après avoir trouvé le problème, nous pouvons prescrire le bon médicament. Tout d'abord, je pense que nous devons résoudre le problème de la transmission de texte en clair http, car ce risque est le plus grand et le plus ordinaire. la capture de paquets peut le capturer. N'est-il pas effrayant d'obtenir le mot de passe ? Puisqu'il existe des problèmes de sécurité avec la transmission en texte brut, nous pouvons garantir la sécurité de la transmission grâce au cryptage

J'utilise toujours le schéma de cryptage MD5, mais j'ajoute une valeur de sel fixe avant de crypter le mot de passe. sel? Est-ce que c'est ajouter du sel ? En fait, c'est presque la même chose. Il vaut mieux dire que c'est ajouter des « assaisonnements ». L'idée de base est la suivante : lorsque l'utilisateur fournit un mot de passe pour la première fois (généralement lors de son inscription), le programme ajoute un peu de "sauce" au mot de passe. Afin de réduire la pression du développement, cet assaisonnement est le même pour chaque utilisateur. hachez à nouveau. Cela empêchera la fuite de mots de passe en texte clair pendant la transmission.

2.2 : Deuxième cryptage

Notez que ce que j'ai mentionné ci-dessus est d'empêcher la fuite de mots de passe en clair, mais cela ne signifie pas que le texte chiffré ne sera pas divulgué si un pirate informatique intercepte votre mot de passe crypté transmis via http ou la base de données. Une fuite se produit et le mot de passe crypté est volé par un pirate informatique. Le pirate informatique obtient la valeur de sel fixe du front-end en analysant le fichier js du front-end. Le pirate peut ensuite effectuer une requête inverse via la table arc-en-ciel pour obtenir le. mot de passe d'origine. À ce stade, l'importance du cryptage secondaire ressort. Le principe de mise en œuvre du cryptage secondaire est de combiner le mot de passe crypté transmis depuis le front-end avec une valeur Salt aléatoire, puis de le chiffrer (notez que cette fois, c'est le salt). valeur sera Il est généré aléatoirement lorsque l'utilisateur se connecte et stocké dans la base de données.

À ce stade, vous avez peut-être le même doute qu'au début, c'est-à-dire que vous avez enregistré la valeur aléatoire du sel dans la base de données, donc si la base de données fuit, que fera votre valeur aléatoire du sel ? Ne serait-il pas possible pour un pirate informatique d'obtenir le mot de passe en déchiffrant les données cryptées et en supprimant la valeur salt ? Oui, il est possible pour un pirate informatique d'obtenir le mot de passe par de tels moyens, mais seulement s'il peut le déchiffrer. Ce que vous devez savoir, c'est que MD5 ne peut pas être piraté directement et ne peut être déchiffré que par la méthode exhaustive. Même si un pirate informatique obtient le mot de passe crypté dans la base de données, mais ne connaît pas le processus de cryptage back-end, il ne pourra pas l'analyser, même s'il connaît en même temps le processus de cryptage, en raison du salage secondaire. et le cryptage secondaire, le texte chiffré est actuellement difficile à analyser. À mesure que la complexité des données cryptées augmente, le coût du piratage augmente de façon exponentielle. Face à un coût aussi énorme, je pense qu'aucun pirate informatique n'est prêt à le faire. essayez-le. Bien entendu, il n'est pas nécessaire d'ajouter du sel à l'avant ou à la fin. Il peut également être inséré au milieu, séparément ou dans l'ordre inverse. Il peut être ajusté de manière flexible lors de la conception du programme, ce qui peut augmenter de manière exponentielle la difficulté. fissuration.

2.3 : Implémentation spécifique

2.3.1 : Enregistrement de l'utilisateur

  • Le front-end effectue un cryptage md5 sur le mot de passe saisi par l'utilisateur (sel fixe)

  • et transmet le mot de passe crypté au backend

  • La fin génère aléatoirement un sel

  • Utilisez le sel généré pour crypter le mot de passe transmis depuis le front-end, puis enregistrez le mot de passe crypté et le sel ensemble dans la base de données

2.3.2 : Connexion de l'utilisateur

  • Front end à l'utilisateur Le mot de passe saisi est crypté md5 (sel fixe)

  • Le mot de passe crypté est transmis au backend

  • Le backend utilise le compte utilisateur pour récupérer les informations utilisateur

  • Le backend exécute md5 sur le mot de passe crypté Chiffrez (retirez le sel), puis comparez-le avec le mot de passe stocké dans la base de données

  • Si la correspondance correspond, la connexion est réussie, sinon la connexion échoue

Trois : Code implémentation

3.1 : Premier cryptage

3.1.1 : Front-end

const params = {
    ...this.ruleForm,
    sex: this.ruleForm.sex === '女' ? '0' : '1',
    //设置密码加密(加上固定salt值)
    password: md5(this.ruleForm.password + this.salt)
}
addEmployee(params).then(res => {
    if (res.code === 1) {
        this.$message.success('员工添加成功!')
        if (!st) {
            this.goBack()
        } else {
            this.ruleForm = {
                username: '',
                'name': '',
                'phone': '',
                password: '',
                // 'rePassword': '',/
                'sex': '男',
                'idNumber': ''
            }
        }
    } else {
        this.$message.error(res.msg || '操作失败')
    }
}

3.1.2 : Backend

/**
* 添加员工
*/
@PostMapping
public R<String> save(@RequestBody Employee employee){
    //生成随机salt值
    String salt = RandomStringUtils.randomAlphanumeric(5);
    //设置随机盐值
    employee.setSalt(salt);
    //设置密码二次加密
    employee.setPassword(DigestUtils.md5DigestAsHex((salt + employee.getPassword()).getBytes()));
 
    boolean save = employeeService.save(employee);
    if(save){
        return R.success("添加成功!");
    }
    return R.error("添加失败!");
}

3.2 : Deuxième cryptage

3.2.1 : Frontend

const params = {
    ...this.loginForm,
    //登录密码加上固定盐值后发送
    password: md5(this.loginForm.password + this.salt),
}
let res = await loginApi(params)
if (String(res.code) === &#39;1&#39;) {
    localStorage.setItem(&#39;userInfo&#39;, JSON.stringify(res.data))
    window.location.href = &#39;/backend/index.html&#39;
} else {
    this.$message.error(res.msg)
    this.loading = false
}

3.2.2 : Backend

/**
 * 员工登录
 */
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
    //1.获取传输过来的加密后的密码值
    String encryPassword = employee.getPassword();
 
    //2.从数据库中获取用户信息
    LambdaQueryWrapper<Employee> lqw = new LambdaQueryWrapper<>();
    lqw.eq(Employee::getUsername,employee.getUsername());
    Employee emp = employeeService.getOne(lqw);
 
    //3.如果没有查询到则返回登陆失败查询结果
    if(emp == null){
        return R.error("没有查询到该用户信息!");
    }
 
    //4.获取注册时保存的随机盐值
    String salt = emp.getSalt();
 
    //5.将页面提交的密码password进行md5二次加密
    String password = DigestUtils.md5DigestAsHex((salt + encryPassword).getBytes());
 
    //6.密码比对,如果不一致则返回登陆失败结果
    if(!emp.getPassword().equals(password)){
        return R.error("密码错误!");
    }
 
    //7.查看员工状态是否可用
    if(emp.getStatus() == 0){
        return R.error("该员工已被禁用!");
    }
    
    //8.登录成功,将员工id存入Session对象并返回登录成功结果
    request.getSession().setAttribute("employee",emp.getId());
    return R.success(emp);
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer