【SaaS - Export项目】23 - Shiro加密实现登录注销,MD5加密算法,加盐加密,shiro凭证匹配器,实现增加用户密码密文存储数据库,登录时通过加盐加密对密文进行比较

   日期:2020-11-13     浏览:199    评论:0    
核心提示:文章目录Shiro凭证匹配器(密码匹配器)1. 普通加密Shiro普通加密(md5)实现1.1 编写MD5加密工具类MD5Utils1.2 测试MD5算法1.3 在applicationContext-shiro.xml添加凭证匹配器(使用默认匹配器)2. 加盐加密2.1 测试加盐加密(添加一个特殊的字符串)2.2 配置自定义的密码匹配器2.3 在applicationContext-shiro.xml添加自定义的凭证匹配器(自定义密码匹配)2.4 修改业务,当添加一个用户的时候进行密码加盐加密保存2.5

文章目录

    • Shiro凭证匹配器(密码匹配器)
      • 1. 普通加密
      • Shiro普通加密(md5)实现
        • 1.1 编写MD5加密工具类MD5Utils
        • 1.2 测试MD5算法
        • 1.3 在applicationContext-shiro.xml添加凭证匹配器(使用默认匹配器)
      • 2. 加盐加密
        • 2.1 测试加盐加密(添加一个特殊的字符串)
        • 2.2 配置自定义的密码匹配器
        • 2.3 在applicationContext-shiro.xml添加自定义的凭证匹配器(自定义密码匹配)
        • 2.4 修改业务,当添加一个用户的时候进行密码加盐加密保存
        • 2.5 shiro退出登录
        • 2.5 测试登录,登录成功(数据库密码已经加盐加密)

Shiro凭证匹配器(密码匹配器)

1. 普通加密

加密:将明文加密成密文保存,常见的用户密码保存在数据库中是需要加密码保存的(防止出现密码泄露造成用户的损失)。
在实际项目中,密码基本上都是密文保存的(加密后保存)

常见加密算法:
MD5,SHA-512,SHA-256等等(或者叠加使用md5(SHA512))

常见加密解密算法地址:
http://www.ttmd5.com/list.php

Shiro普通加密(md5)实现

实现步骤:
1)对数据库密码进行md5加密
使用mysql的md5函数对密码进行加密,然后直接修改数据库的用户密码测试登录。
2) 在applicationContext-shiro.xml,添加加密认证配置

1.1 编写MD5加密工具类MD5Utils


public class MD5Utils { 
    //参1 传入的明文
    public static String stringToMD5(String plainText) { 
        byte[] secretBytes = null;
        try { 
            //对明文的字节进行摘要加密
            secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());
        } catch (NoSuchAlgorithmException e) { 
            throw new RuntimeException("没有找到MD5算法");
        }

        //radix参数 16位或者32位(加密之后的位数)
        String md5code = new BigInteger(1, secretBytes).toString(16);

        //补0操作,一个字节转两位的16进制
        for (int i = 0; i < 32 - md5code.length(); i++) { 
            md5code = "0" + md5code;
        }
        return md5code;
    }
}

1.2 测试MD5算法


public class MD5UtilsTest { 

    //测试MD5工具类加密
    @Test
    public void stringToMD5() { 
        //对123456进行MD5加密
        String result = MD5Utils.stringToMD5("123456");
        //md5(123456)= e10adc3949ba59abbe56e057f20f883e
        System.out.println(result);
    }

    //测试shiro自带的hash.Md5Hash算法加密,(shiro也集成常用的加密的算法md5,sha-1)
    @Test
    public void test02() { 
        // 对123456加密
        Md5Hash md5Hash = new Md5Hash("123456");
        System.out.println(md5Hash.toString()); //e10adc3949ba59abbe56e057f20f883e
    }
}

1.3 在applicationContext-shiro.xml添加凭证匹配器(使用默认匹配器)

    <!-- 配置一个密码的匹配器 -->
    <!-- 123456 是用户提交过来的密码明文, 密码的匹配器,得到密文,与数据库的密码 -->
    <!--创建凭证匹配器-->
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <!--指定加密算法-->
        <property name="hashAlgorithmName" value="md5"/>
    </bean>
    <!-- 3.创建Realm(类似dao),在AuthRealm类上就不需要加@Component注解了 -->
    <bean id="authRealm" class="com.xgf.web.shiro.AuthRealm">
        <!-- 使用自定义匹配器(密码) -->
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
    </bean>

2. 加盐加密

1)为什么要加盐(加盐实现加密的意义)

如果只是单纯使用md5或sha1进行加密,容易被人利用"彩虹表"撞库来破解密码,导致密码不安全!这时可以进行加盐加密来解决。
破解方法:将很多的字符串进行调用加密算法,生成对应的很多的密文,然后根据密文倒过来查表(这个表非常的大比如100G,时间虽然久一点,但是能够破解),得出明文(撞库更具密文查找明文)。

2)如何加盐加密

添加一个特殊字符串,别人推导明文的时候,还需要去推导那个特殊的字符串,增加推导任务,造成算率不够导致推导不出来等。

3)shiro加盐加密步骤

1、编写代码对密码加盐加密
2、编写自定义凭证匹配器
3、在applicationContext-shiro.xml,添加自定义凭证匹配器

2.1 测试加盐加密(添加一个特殊的字符串)

MD5UtilsTest

//测试加盐加密(添加一个特殊字符串)
    @Test
    public void test03() { 
        //参1:传入明文 参2:加盐(特殊字符串)
        Md5Hash md5Hash = new Md5Hash("123456","strive_day@163.com");
        System.out.println(md5Hash.toString());//2f660a3a69e023b9033c83ef3d418c9b
    }
    
    //测试加另一个盐(另一个字符串)
    @Test
    public void test04() { 
        Md5Hash md5Hash = new Md5Hash("123456","study@export.com");//参1 传入明文 参2盐
        System.out.println(md5Hash.toString());//4154661a85ae8bafac91433e7003f4a2和上面的密文不一样,因为特殊字符串盐不一样
    }

2.2 配置自定义的密码匹配器

CustomCredentialsMatcher


public class CustomCredentialsMatcher extends SimpleCredentialsMatcher { 
    private Logger l = LoggerFactory.getLogger(this.getClass());

    //将密码加密成密文,但需要使用账号(这里账号是邮箱)作盐
    //subject.login(token) 获取页面提交的密码 (比如123456) 通过加盐加密转为 -> 密文1
    //info 调relam 查询数据库中的密码(数据库中的密码存储就是加密存储的) -> 密文2
    //通过比较密文1(用户输入的值)和密文2(数据库中的值),来判断用户输入是否正确
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { 
        //token获取账号密码
        UsernamePasswordToken t = (UsernamePasswordToken) token;
        String email = t.getUsername(); //获取用户名(邮箱)
        //密码是char[] '1','2','3' => "123" new String(char[])
        String pwd1 = new String(t.getPassword());  //密码获取的是字符数组,转换为字符串
        l.info("doCredentialsMatch 用户输入的密码明文pwd1 = "+pwd1);
        //进行加盐加密,得到用户输入的密码明文加密后的密文
        Md5Hash md5Hash = new Md5Hash(pwd1, email);//参1 传入明文 参2盐
        pwd1 = md5Hash.toString();  //转换为字符串
        l.info("doCredentialsMatch 用户输入的密码加盐加密后pwd1 "+pwd1);

        //读取数据库的密码,数据库存储的就是密文
        String pwd2 = (String) info.getCredentials();
        l.info("doCredentialsMatch 数据库的密码密文pwd2 = "+pwd2);
        if (pwd1.equals(pwd2)) { 
            return true;//密码正确(两个密文比较)
        } else { 
            return false;//密码不正确
        }

    }
}

2.3 在applicationContext-shiro.xml添加自定义的凭证匹配器(自定义密码匹配)

    <!--使用自己定义的匹配器-->
    <bean id="credentialsMatcher2" class="com.xgf.web.utils.CustomCredentialsMatcher"></bean>

    <!-- 3.创建Realm(类似dao),在AuthRealm类上就不需要加@Component注解了 -->
    <bean id="authRealm" class="com.xgf.web.shiro.AuthRealm">
        <!-- 使用自定义匹配器(密码) -->
        <property name="credentialsMatcher" ref="credentialsMatcher2"/>
    </bean>

2.4 修改业务,当添加一个用户的时候进行密码加盐加密保存

UserServiceImpl

    @Override
    public void saveUser(User user) { 
        String uuid= UUID.randomUUID().toString();
        user.setUserId(uuid);
        //原来保存用户使用的密码是明文,现在需要对它进行加密
        if(user.getPassword()!=null){ //不能对空字符串进行加密
            //使用shiro自带的加密Md5Hash
            //参1:密码明文 参2:盐(按照邮箱设置盐)
            Md5Hash md5Hash = new Md5Hash(user.getPassword(),user.getEmail());
            user.setPassword(md5Hash.toString());
        }
        l.info("save user = " + user);
        iUserDao.save(user);
    }

2.5 shiro退出登录

UserController

    //使用shiro退出登录(不再使用前面的普通登录退出了)
    @RequestMapping(path = "/loginOut-shiro", method = { RequestMethod.GET, RequestMethod.POST})
    public String loginOutShiro(){ 
        //删除session中的用户信息
        Subject subject = SecurityUtils.getSubject();
        //shiro退出登录
        subject.logout();
        l.info("loginOut-shiro注销用户");
        return "redirect:/login-shiro.jsp";
    }

header.jsp的注销方式改为shiro注销

<%-- 非加密方式注销 --%>
<%--<a href="${path}/system/user/loginOut" class="btn btn-default btn-flat">注销</a>--%>
<%--使用shiro退出 subject.logout(); --%>
<a href="${path}/system/user/loginOut-shiro" class="btn btn-default btn-flat">注销</a>

2.5 测试登录,登录成功(数据库密码已经加盐加密)


 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服