常见登录密码加密方式

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 常见登录密码加密方式

1 常见的加密方式

由于在学习JWT的时候会涉及使用很多加密算法, 所以在这里做下扫盲, 简单了解就可以

加密算法种类有:

1.1.可逆加密算法

解释: 加密后, 密文可以反向解密得到密码原文.

1.1.1. 对称加密

用的较少因为不安全,要把秘钥也给别人

文件加密和解密使用相同的密钥,即加密密钥也可以用作解密密钥

解释: 在对称加密算法中,数据发信方将明文和加密密钥一起经过特殊的加密算法处理后,使其变成复杂的加密密文发送出去,收信方收到密文后,若想解读出原文,则需要使用加密时用的密钥以及相同加密算法的逆算法对密文进行解密,才能使其回复成可读明文。在对称加密算法中,使用的密钥只有一个,收发双方都使用这个密钥,这就需要解密方事先知道加密密钥。


优点: 对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高。


缺点: 没有非对称加密安全.


用途: 一般用于保存用户手机号、身份证等敏感但能解密的信息。


常见的对称加密算法有: AES、DES、3DES、Blowfish、IDEA、RC4、RC5、RC6、HS256

1.1.2. 非对称加密

两个密钥:公开密钥(publickey)和私有密钥,公有密钥加密,私有密钥解密


**解释: ** 同时生成两把密钥:私钥和公钥,私钥隐秘保存,公钥可以下发给信任客户端.


加密与解密:


私钥加密,持有公钥才可以解密

公钥加密,持有私钥才可解密

签名:


私钥签名, 持有公钥进行验证是否被篡改过.

**优点: ** 非对称加密与对称加密相比,其安全性更好;


缺点: 非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。

用途: 一般用于签名和认证。私钥服务器保存, 用来加密, 公钥客户拿着用于对于令牌或者签名的解密或者校验使用.


常见的非对称加密算法有: RSA、DSA(数字签名用)、ECC(移动设备用)、RS256 (采用SHA-256 的 RSA 签名)

1.2.不可逆加密算法

解释: 一旦加密就不能反向解密得到密码原文.

种类: Hash加密算法, 散列算法, 摘要算法等

**用途:**一般用于效验下载文件正确性,一般在网站上下载文件都能见到;存储用户敏感信息,如密码、 卡号等不可解密的信息。

常见的不可逆加密算法有:MD5、SHA、HMAC

1.3.Base64编码

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一。Base64编码可用于在HTTP环境下传递较长的标识信息。采用Base64Base64编码解码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。注意:Base64只是一种编码方式,不算加密方法。


在线编码工具:


http://www.jsons.cn/img2base64/

2 密码加密的方式选型

common工程test下测试

2.1 MD5密码加密

java //md5加密 DegestUtils:spring框架提供的工具类 String md5Str = DigestUtils.md5DigestAsHex("abc".getBytes());

System.out.println(md5Str);//900150983cd24fb0d6963f7d28e17f72

md5相同的密码每次加密都一样,不太安全

2.2 手动加密(md5+随机字符串)

在md5的基础上手动加盐(salt)处理

//uername:zhangsan  password:123   salt:随时字符串
String salt = RandomStringUtils.randomAlphanumeric(10);//获取一个10位的随机字符串
System.out.println(salt);
String pswd = "123"+salt;
String saltPswd = DigestUtils.md5DigestAsHex(pswd.getBytes());
System.out.println(saltPswd);

这样同样的密码,加密多次值是不相同的,因为加入了随机字符串

2.3 . BCrypt密码加密

在用户模块,对于用户密码的保护,通常都会进行加密。我们通常对密码进行加密,然后存放在数据库中,在用户进行登录的时候,将其输入的密码进行加密然后与数据库中存放的密文进行比较,以验证用户密码是否正确。 目前,MD5和BCrypt比较流行。相对来说,BCrypt比MD5更安全。

BCrypt 官网http://www.mindrot.org/projects/jBCrypt/

(1)我们从官网下载源码

(2)新建工程,将源码类BCrypt拷贝到工程

(3)新建测试类,main方法中编写代码,实现对密码的加密


java String gensalt = BCrypt.gensalt();//这个是盐 29个字符,随机生成 System.out.println(gensalt); String password = BCrypt.hashpw("123456", gensalt); //根据盐对密码进行加密 System.out.println(password);//加密后的字符串前29位就是盐


(4)新建测试类,main方法中编写代码,实现对密码的校验。BCrypt不支持反运算,只支持密码校验。


java boolean checkpw = BCrypt.checkpw("123456", "2a2a10$61ogZY7EXsMDWeVGQpDq3OBF1.phaUu7.xrwLyWFTOu8woE08zMIW"); System.out.println(checkpw);

3 jwt介绍

3.1 token认证-面试

随着 Restful API、微服务的兴起,基于 Token 的认证现在已经越来越普遍。基于token的用户认证是一种服务端无状态的认证方式,所谓服务端无状态指的token本身包含登录用户所有的相关数据,而客户端在认证后的每次请求都会携带token,因此服务器端无需存放token数据。


当用户认证后,服务端生成一个token发给客户端,客户端可以放到 cookie 或 localStorage 等存储中,每次请求时带上 token,服务端收到token通过验证后即可确认用户身份。

20210216182043788.png

3.2 什么是JWT?

我们现在了解了基于token认证的交互机制,但令牌里面究竟是什么内容?什么格式呢?市面上基于token的认证方式大都采用的是JWT(Json Web Token)。


JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。


JWT令牌结构:


JWT令牌由Header、Payload、Signature三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz


Header

头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC、SHA256或RSA)。


一个例子:


json { "alg": "HS256", "typ": "JWT" }


将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。


Payload

第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比

如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。

此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。

一个例子:


json { "sub": "1234567890", "name": "456", "admin": true }


最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。


Signature

第三部分是签名,此部分用于防止jwt内容被篡改。

这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明

签名算法进行签名。

一个例子:


shell HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)


base64UrlEncode(header):jwt令牌的第一部分。

base64UrlEncode(payload):jwt令牌的第二部分。

secret:签名所使用的密钥。


下图中包含一个生成的jwt令牌:

3.3 生成token

查看utils工程

需要引入jwt相关依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
</dependency>

工具类

package com.oldlu.utils.common;
import io.jsonwebtoken.*;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;
public class AppJwtUtil {
    // TOKEN的有效期一天(S)
    private static final int TOKEN_TIME_OUT = 3_600;
    // 加密KEY
    private static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";
    // 最小刷新间隔(S)
    private static final int REFRESH_TIME = 300;
    // 生产ID
    public static String getToken(Long id){
        Map<String, Object> claimMaps = new HashMap<>();
        claimMaps.put("id",id);
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTime))  //签发时间
                .setSubject("system")  //说明
                .setIssuer("oldlu") //签发者信息
                .setAudience("app")  //接收用户
                .compressWith(CompressionCodecs.GZIP)  //数据压缩方式
                .signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000))  //过期时间戳
                .addClaims(claimMaps) //cla信息
                .compact();
    }
    /**
     * 获取token中的claims信息
     *
     * @param token
     * @return
     */
    private static Jws<Claims> getJws(String token) {
            return Jwts.parser()
                    .setSigningKey(generalKey())
                    .parseClaimsJws(token);
    }
    /**
     * 获取payload body信息
     *
     * @param token
     * @return
     */
    public static Claims getClaimsBody(String token) {
        try {
            return getJws(token).getBody();
        }catch (ExpiredJwtException e){
            return null;
        }
    }
    /**
     * 获取hearder body信息
     *
     * @param token
     * @return
     */
    public static JwsHeader getHeaderBody(String token) {
        return getJws(token).getHeader();
    }
    /**
     * 是否过期
     *
     * @param claims
     * @return -1:有效,0:有效,1:过期,2:过期
     */
    public static int verifyToken(Claims claims) {
        if(claims==null){
            return 1;
        }
        try {
            claims.getExpiration()
                    .before(new Date());
            // 需要自动刷新TOKEN
            if((claims.getExpiration().getTime()-System.currentTimeMillis())>REFRESH_TIME*1000){
                return -1;
            }else {
                return 0;
            }
        } catch (ExpiredJwtException ex) {
            return 1;
        }catch (Exception e){
            return 2;
        }
    }
    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
    public static void main(String[] args) {
       /* Map map = new HashMap();
        map.put("id","11");*/
        System.out.println(AppJwtUtil.getToken(1102L));
        Jws<Claims> jws = AppJwtUtil.getJws("eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAADWLQQqEMAwA_5KzhURNt_qb1KZYQSi0wi6Lf9942NsMw3zh6AVW2DYmDGl2WabkZgreCaM6VXzhFBfJMcMARTqsxIG9Z888QLui3e3Tup5Pb81013KKmVzJTGo11nf9n8v4nMUaEY73DzTabjmDAAAA.4SuqQ42IGqCgBai6qd4RaVpVxTlZIWC826QA9kLvt9d-yVUw82gU47HDaSfOzgAcloZedYNNpUcd18Ne8vvjQA");
        Claims claims = jws.getBody();
        System.out.println(claims.get("id"));
    }
}


目录
相关文章
|
4月前
|
存储 NoSQL 数据库
认证服务---整合短信验证码,用户注册和登录 ,密码采用MD5加密存储 【二】
这篇文章讲述了在分布式微服务系统中添加用户注册和登录功能的过程,重点介绍了用户注册时通过远程服务调用第三方服务获取短信验证码、使用Redis进行验证码校验、对密码进行MD5加密后存储到数据库,以及用户登录时的远程服务调用和密码匹配校验的实现细节。
认证服务---整合短信验证码,用户注册和登录 ,密码采用MD5加密存储 【二】
|
2月前
|
存储 Java 数据库
密码专辑:对密码加盐加密,对密码进行md5加密,封装成密码工具类
这篇文章介绍了如何在Java中通过加盐和加密算法(如MD5和SHA)安全地存储密码,并提供了一个密码工具类PasswordUtils和密码编码类PasswordEncoder的实现示例。
59 10
密码专辑:对密码加盐加密,对密码进行md5加密,封装成密码工具类
|
2月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
40 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
2月前
|
安全 算法 Java
数据库信息/密码加盐加密 —— Java代码手写+集成两种方式,手把手教学!保证能用!
本文提供了在数据库中对密码等敏感信息进行加盐加密的详细教程,包括手写MD5加密算法和使用Spring Security的BCryptPasswordEncoder进行加密,并强调了使用BCryptPasswordEncoder时需要注意的Spring Security配置问题。
202 0
数据库信息/密码加盐加密 —— Java代码手写+集成两种方式,手把手教学!保证能用!
|
3月前
|
存储 安全 算法
RSA在手,安全我有!Python加密解密技术,让你的数据密码坚不可摧
【9月更文挑战第11天】在数字化时代,信息安全至关重要。传统的加密方法已难以应对日益复杂的网络攻击。RSA加密算法凭借其强大的安全性和广泛的应用场景,成为保护敏感数据的首选。本文介绍RSA的基本原理及在Python中的实现方法,并探讨其优势与挑战。通过使用PyCryptodome库,我们展示了RSA加密解密的完整流程,帮助读者理解如何利用RSA为数据提供安全保障。
145 5
|
4月前
|
存储 算法 Java
在Java中使用MD5对用户输入密码进行加密存储、同时登录验证。
这篇文章详细介绍了在Java项目中如何使用MD5算法对用户密码进行加密存储和登录验证,包括加入依赖、编写MD5工具类、注册时的密码加密和登录时的密码验证等步骤,并通过示例代码和数据库存储信息展示了测试效果。
在Java中使用MD5对用户输入密码进行加密存储、同时登录验证。
|
3月前
|
安全 数据安全/隐私保护 Python
情书也能加密?Python AES&RSA,让每一份数据都充满爱的密码
【9月更文挑战第8天】在这个数字化时代,情书不再局限于纸笔,也可能以电子形式在网络中传递。为了确保其安全,Python提供了AES和RSA等加密工具,为情书编织爱的密码。首先,通过安装pycryptodome库,我们可以利用AES对称加密算法高效保护数据;接着,使用RSA非对称加密算法加密AES密钥和IV,进一步增强安全性。即使情书被截获,没有正确密钥也无法解读内容。让我们用Python为爱情编织一张安全的网,守护每份珍贵情感。
54 2
|
4月前
|
数据采集 数据可视化 数据挖掘
基于python django的scrapy去哪儿网数据采集与分析,包括登录注册和可视化大屏,有md5加密
本文介绍了一个基于Python和Django框架,使用Scrapy进行去哪儿网数据采集与分析的项目,包括实现登录注册功能、MD5加密以及通过可视化大屏展示分析结果的综合系统。
基于python django的scrapy去哪儿网数据采集与分析,包括登录注册和可视化大屏,有md5加密
|
4月前
|
安全 数据安全/隐私保护 Python