Shiro--密码加密

散列算法

散列算法一般用于生成一段文本的摘要信息,将内容可以生成摘要,无法将摘要转成原始内容。

  • 散列算法不可逆
  • 散列算法常用于对密码进行散列
  • 常用的散列算法有 MD5、SHA

一般散列算法需要提供一个 salt (盐) 与原始内容生成摘要信息,这样做的目的是为了安全性

比如:111111 的 md5值是:96e79218965eb72c92a549dd5a330112,
拿着 96e79218965eb72c92a549dd5a330112 去md5破解网站很容易进行破解

如果要是对111111和salt(盐,一个随机数)进行散列,这样虽然密码都是111111,但是 加不同的盐会生成不同的散列值

@Test
public void test() { //md5加密,不加盐
	String password_md5 = new Md5Hash("111111").toString(); 			
	System.out.println("password_md5=" + password_md5);
	//md5加密,加盐 一次散列
	String password_md5_salt_1 = new Md5Hash("111111", "imcode", 1).toString(); 
	System.out.println("password_md5_salt_1=" + password_md5_salt_1);
	//两次散列相当于md5(md5())
	String password_md5_salt_2 = new Md5Hash("111111", "imcode", 2).toString(); 
	System.out.println("password_md5_salt_2=" + password_md5_salt_2);
	//使用SimpleHash
	String password_md5_simpleHash = new SimpleHash("MD5", "111111", "imcode", 2).toString();
	System.out.println("password_md5_simpleHash=" + password_md5_simpleHash); 
}

加密工具类

public class MD5Util {
    // 散列次数
    private static int hashIterations = 3;

    private static String salt = "ak47";
    /**
     * md5加密工具类
     * @param source
     * @param salt
     * @return
     */
    public static String md5(String source, String salt) {
        return new Md5Hash(source, salt, hashIterations).toString();
    }

    public static String md5_salt(String source) {
        return new Md5Hash(source, salt, hashIterations).toString();
    }
}

Realm

public class ShiroRealm extends AuthorizingRealm {


    /**
     * 登录认证
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

        // 1.获取用户输入的用户名
        String username = token.getUsername();
        // 2.获取用户输入的密码
        String password = new String(token.getPassword());

        // 3.根据用户名去DB查询对应的用户信息,密码为加密后的密文
        User user = new User("admin", "3635b070bdf50a94f350c1d050ab1b61", 0);
        //User user = new User("admin", "123456", 0);
        if (!user.getUsername().equals(username)) {
            throw new UnknownAccountException("用户名不存在");
        }
        if (!user.getPassword().equals(password)) {
            throw new CredentialsException("密码错误");
        }
        if (user.getStatus() == 1) {
            throw new DisabledAccountException("账号被禁用");
        }
        if (user.getStatus() == 2) {
            throw new LockedAccountException("账号被锁定");
        }

        System.out.println("认证成功...");

        // 创建简单认证信息对象
        SimpleAuthenticationInfo info =
                new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());

        return info;
    }


    /**
     * 授权
     * 将认证通过的用户的角色和权限信息设置到对应用户主体上
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        String username = principals.getPrimaryPrincipal().toString();


        //模拟从数据库获取当前用户的角色 通过用户名查询该用户拥有的角色名称
        Set<String> roleNameSet = new HashSet<>();
        roleNameSet.add("系统管理员");
        //roleNameSet.add("系统运维");

        //模拟从数据库获取当前用户的权限 通过用户名查询该用户拥有的权限名称
        Set<String> permissionNameSet = new HashSet<>();
        permissionNameSet.add("sys:user:list"); // 查看列表
        permissionNameSet.add("sys:user:info"); // 查看用户详情
        permissionNameSet.add("sys:user:create");// 创建用户
        permissionNameSet.add("sys:user:update");// 修改用户
        permissionNameSet.add("sys:user:delete");// 删除用户

        // 简单授权信息对象,对象中包含用户的角色和权限信息
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roleNameSet);
        info.addStringPermissions(permissionNameSet);

        System.out.println("授权完成....");
        return info;
    }


}

测试:

@Test
    public void test04() {
        // 模拟从客户端接收到用户登录输入的用户名和密码(明文)
        String username = "admin";
        String password = "123456";


        // 将明文的密码加密成密文
        String salt = MD5Util.md5_salt(username + password);
        password = MD5Util.md5(password, salt);

        // 登录认证
        ShiroUtil.login(username, password);
    }

控制台打印:

认证成功...
[DEBUG] Looked up AuthenticationInfo [admin] from doGetAuthenticationInfo 
[DEBUG] AuthenticationInfo caching is disabled for info [admin].  Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false]. 
[DEBUG] Performing credentials equality check for tokenCredentials of type [[C and accountCredentials of type [[C] 
[DEBUG] Both credentials arguments can be easily converted to byte arrays.  Performing array equals comparison 
[DEBUG] Authentication successful for token [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false].  Returned account [admin] 
[DEBUG] No sessionValidationScheduler set.  Attempting to create default instance. 
[INFO] Enabling session validation scheduler... 
[DEBUG] Creating new EIS record for new session instance [org.apache.shiro.session.mgt.SimpleSession,id=null] 
Apache Shiro 是一个强大且易用的 Java 安全框架,主要用于身份验证(Authentication)、授权(Authorization)、会话管理(Session Management)和加密(Cryptography)等功能。 在加密方面,`shiro-core` 提供了一些常用的加密工具类和接口,尤其适用于密码存储、哈希加盐、加密解密等场景。 --- ### ✅ `shiro-core` 常用加密功能 #### 1. **Hash 加密(哈希)** Shiro 提供了多种哈希算法支持,如 MD5、SHA-1、SHA-256 等,常用于密码加密。 ```java import org.apache.shiro.crypto.hash.SimpleHash; String hash = new SimpleHash("SHA-256", "password", null, 1).toString(); System.out.println("SHA-256: " + hash); ``` - **支持算法**:MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512 等。 - **迭代次数**:可以设置多次哈希(如 `new SimpleHash("SHA-256", password, salt, 1024)`)。 #### 2. **加盐(Salt)** Shiro 支持使用盐值增强密码安全性。 ```java String salt = "random_salt"; String hashed = new SimpleHash("SHA-256", "password", salt, 1024).toString(); ``` - **盐值生成**:也可以使用 `ByteSource.Util.bytes(UUID.randomUUID())` 生成随机盐。 #### 3. **对称加密(AES)** Shiro 提供了 AES 加密支持,用于加密/解密数据。 ```java import org.apache.shiro.crypto.AesCipherService; import org.apache.shiro.util.ByteSource; AesCipherService cipherService = new AesCipherService(); cipherService.setKeySize(128); // 设置密钥长度 ByteSource ciphertext = cipherService.encrypt("secret".getBytes(), "key1234567890".getBytes()); System.out.println("加密结果: " + ciphertext.toHex()); ``` - **解密**:`cipherService.decrypt(ciphertext.getBytes(), keyBytes);` #### 4. **Base64 编码/解码** Shiro 提供了简单的 Base64 工具类: ```java import org.apache.shiro.codec.Base64; String encoded = Base64.encodeToString("hello".getBytes()); byte[] decoded = Base64.decode(encoded); ``` #### 5. **编码工具(Hex、Bytes)** Shiro 提供了 `Hex` 工具类,用于字节与十六进制字符串之间的转换: ```java import org.apache.shiro.codec.Hex; String hex = Hex.encodeToString("hello".getBytes()); byte[] bytes = Hex.decode(hex); ``` --- ### ✅ 总结:Shiro 加密常用功能 | 功能 | 说明 | |------|------| | `SimpleHash` | 支持多种哈希算法,支持加盐和迭代 | | `AesCipherService` | 提供 AES 对称加密和解密 | | `Base64` | Base64 编码/解码 | | `Hex` | 十六进制与字节之间的转换 | | `ByteSource` | 封装字节数据,支持多种编码方式 | --- ### ✅ 使用场景建议 - **密码存储**:推荐使用 `SimpleHash` + 盐 + 多次迭代(如 SHA-256 + 1024 次) - **敏感数据加密**:使用 `AesCipherService` 进行加密存储或传输 - **数据编码**:使用 `Base64` 或 `Hex` 进行数据格式转换 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值