shiro 密码加密和解密

本文介绍使用Shiro进行密码加密的方法及自定义密码验证过程。通过配置文件或与Spring集成来指定加密算法,如MD5,并利用SimpleCredentialsMatcher或HashedCredentialsMatcher进行密码验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:对于登录的密码信息加密,增加密码破解难度。在密码使用Shiro的hash加密方法和自定义方法加密算法。

步骤
1.告诉shiro密码使用何种加密方法
2.告诉shiro如何验证加密密码是否正确

1.告诉shiro密码使用何种加密方法
通过Credentials 和 CredentialsMatcher告诉shiro什么加密和密码校验
在配置文件上使用如何使用它们俩告诉shiro如何加密和校验

INI 文件的main 增加如下,可以参考shiro 使用 InI 验证
myRealm = com.demo.MyRealm 
customMatcher =  com.demo.CustomCredentialsMatcher
myRealm.credentialsMatcher = $customMatcher

与spring集成告诉shiro
<bean id="shiroDbRealm" class="service.ShiroDbRealm">
<!--验证方式-->
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name="hashAlgorithmName" value="MD5"/>
            </bean>
        </property>
    </bean>
2.告诉shiro如何验证加密密码是否正确
告诉shiro如何验证加密密码,通过SimpleCredentialsMatcherHashedCredentialsMatcher

SimpleCredentialsMatcher(简单证明匹配): SimpleCredentialsMatcher对存储的用户凭证和从AuthenticationToken提交的用户凭证直接执行相等的检查。

HashedCredentialsMatcher:取代将凭证按它们原始形式存储并执行原始数据的对比,存储终端用户的凭证(如密码)更安全的办法是在存储数据之前,先进行hash运算。

密码校验方法继承SimpleCredentialsMatcherHashedCredentialsMatcher类,实现doCredentialsMatch方法

示类
-------------------------------------------------------------------------------------------------------------
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {

    @Override
    public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

        Object tokenCredentials = encrypt(String.valueOf(token.getPassword()));
        Object accountCredentials = getCredentials(info);
        //将密码加密与系统加密后的密码校验,内容一致就返回true,不一致就返回false
        return equals(tokenCredentials, accountCredentials);
    }

    //将传进来密码加密方法
    private String encrypt(String data) {
        String sha384Hex = new Sha384Hash(data).toBase64();
        System.out.println(data + ":" + sha384Hex);
        return sha384Hex;
    }
}


-----------------关于自定义Realm,通过Realm与应用交互验证身份
public class MyRealm extends AuthorizingRealm {

    private static Logger logger = LoggerFactory.getLogger(MyRealm.class);

    public MyRealm() {
        super();    //To change body of overridden methods use File | Settings | File Templates.
    }
//认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;

        String username = usernamePasswordToken.getUsername();

/*        logger.info("用户名:{}", token.getUsername());
        logger.info("用户密码:{}", token.getPassword());*/


        if (username == null) {
            throw new AccountException("用户名不能为空");
        }

        //TODO 取数据库
        User user = new User();
        user.setName("汤汤");
      //  user.setPassWord("5201314");
        user.setPassWord("Mug2tZdS/WCdxOOfCHXPcdQyVT5kqBimrBM04UEj9Dma+XaasHvZZckw/OGjWj8J");
        user.setRoles("admin");
        return new SimpleAuthenticationInfo(user.getName(), user.getPassWord(), getName());
    }
   //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            throw new AuthorizationException("Principal对象不能为空");
        }

      /*  String userName = (String) principals.fromRealm(getName()).iterator().next();*/
        String userName = (String) principals.fromRealm(getName()).iterator().next();

        if (userName != null && userName.equals("汤汤")) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
           /* info.addStringPermission("admin");*/

            List<String> rolesList = new ArrayList<String>();
            rolesList.add("admin");

            info.addRoles(rolesList);
            return info;
        } else {
            return null;
        }
    }
}


### 关于Shiro框架中的密码处理 Apache Shiro是一个强大且易用的Java安全框架, 可以帮助完成认证、授权、加密等功能[^1]。然而,在讨论Shiro框架内的密码解密之前,重要澄清一点:Shiro并不直接支持传统意义上的“解密”。相反,它主要采用散列(hash)函数来保护存储的密码。 #### 密码加密机制 对于密码的安全存储,Shiro推荐使用带有盐(salt)值的单向散列算法。这种方式确保即使两个用户的原始密码相同,由于各自不同的盐值,最终产生的哈希也会不同,从而增加了暴力破解难度[^2]。 ```java import org.apache.shiro.crypto.hash.SimpleHash; // 使用SHA-256作为散列算法,并加入随机生成的Salt String algorithmName = "SHA-256"; Object source = "original_password"; // 用户输入的明文密码 Object salt = new SecureRandomNumberGenerator().nextBytes(); // 自动生成Salt int hashIterations = 1024; // 散列迭代次数 SimpleHash hash = new SimpleHash(algorithmName, source, salt, hashIterations); String encodedPassword = hash.toHex(); ``` 这段代码展示了如何利用`SimpleHash`类配合特定参数创建一个经过多次迭代计算后的散列字符串。这不仅提高了安全性,而且使得每次运行都会产生独一无二的结果,即便相同的初始密码也不例外。 #### 所谓的“解密” 实际上,在实际应用中并没有真正意义上去“解密”这些已经过散列运算的数据。当验证用户身份时,系统会再次执行同样的散列过程(即基于同一套配置下的algorithm name, iterations number stored salt value),并将新生成的结果同数据库里保存下来的hash做对比。如果两者匹配,则认为用户提供的是正确的密码;反之则视为错误尝试。 因此,“解密”的概念在这里并不存在&mdash;&mdash;至少不是指恢复原本未被修改过的字符形式。取而代之的是重新构建一次完全一致的过程以便比较两者的输出是否相等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值