Shiro___加密加盐迭代

Posted zhangsonglin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro___加密加盐迭代相关的知识,希望对你有一定的参考价值。

简单的模拟账号密码登入,为了简便就不去数据库真实的查询了

这里先使用MD5加盐迭代加密,算出我们的密码加密结果
MD5是不可逆的,单向加密,所以我们需要对原始数据进行加密后与加密的数据对比,而不是去解密

package com.test;

import org.apache.shiro.crypto.hash.Md5Hash;
/**
 * 对123456加密,
 * 盐值(salt):zsl
 * 迭代次数:6
 * 加密结果:70fc2a964652cf72d7f67022a7951e51
 * @author Administrator
 *
 */
public class MD5Test 

    public static void main(String[] args) 
        Md5Hash mdh = new Md5Hash("123456", "zsl", 6);
        System.out.println(mdh);
        //70fc2a964652cf72d7f67022a7951e51
    

自定义的Realm:
认证方法

package com.test;

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.SimpleByteSource;

public class MyRealm extends AuthorizingRealm

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) 
        // 获取当前登录的账号
        Object principal = principals.getPrimaryPrincipal();
        
        List<String> roleList = new ArrayList<>();
        List<String> psList = new ArrayList<>();
        roleList.add("role1");
        roleList.add("role2");
        roleList.add("role3");
        
        psList.add("create");
        psList.add("query");
        psList.add("delete");
        
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        
        info.addRoles(roleList);
        info.addStringPermissions(psList);
        
        return info;
    

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException 
        // TODO Auto-generated method stub
        //获取账号信息
        Object principal = arg0.getPrincipal();
        //从数据库等数据源获取数据
        String name = "root";
        
        if (!name.equals(principal)) //低质量的匹配认证
            return null;
        
        //根据账号去数据库查询出密码
        //经过加密加盐迭代后的密码,这里模拟从数据库查询出了已加密的结果
        String pwd = "70fc2a964652cf72d7f67022a7951e51";
        
        //我们知道自定义的Realm是不验证密码的,实际验证密码的是AuthenticatingRealm中的AuthenticationInfo方法
        //这里的SimpleAuthenticationInfo就是封装好的验证密码的方法
        //这里提供了new SimpleByteSource("zsl"),zsl是盐值,而迭代次数在ini中
        AuthenticationInfo  info = new SimpleAuthenticationInfo(principal,pwd,new SimpleByteSource("zsl"),  "MyRealm");
        
        return info;
    

在没有整合其他框架,如Spring前,我们这里配置ini文件来代替xml以及数据库
Shiro.ini:

[main] #定义凭证匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #散列算法 credentialsMatcher.hashAlgorithmName=md5 #散列次数 credentialsMatcher.hashIterations=1 #将凭证匹配器设置到realm customRealm=com.dpb.realm.MyRealm customRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$customRealm

测试:

public class Test 
    public static void main(String[] args) 
        // 获取SecurityManagerFactory对象
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        // 根据工厂对象获取SecurityManager对象
        SecurityManager manager = factory.getInstance();
        // 将SecurityManager添加到运行环境中
        SecurityUtils.setSecurityManager(manager);
        
        // 获取Subject对象
        Subject subject = SecurityUtils.getSubject();   
        // 获取对应的认证令牌
        AuthenticationToken token = new UsernamePasswordToken("root", "123456") ;
        // 做登录认证
        try 
            subject.login(token);
            System.out.println("登录成功....");
         catch (UnknownAccountException e) 
            System.out.println("账号错误...");
         catch (IncorrectCredentialsException e) 
            System.out.println("密码错误...");
        
        System.out.println(subject.isAuthenticated());

这里是类似于把密码加密加盐迭代后的结果存到数据库,然后客户端请求来的密码是没有加密加盐迭代的,我们需要对它也同样的进行加密加盐迭代,与通过账号到数据库查询出来的密码进行比对。我们知道自定义的Realm是不验证密码的,实际验证密码的是AuthenticatingRealm中的AuthenticationInfo方法去验证密码,所以我们这里自定义的Realm继承AuthorizingRealm重写了doGetAuthenticationInfo方法,这样我们就可以对我们的账号和密码进行相关业务操作。

以上是关于Shiro___加密加盐迭代的主要内容,如果未能解决你的问题,请参考以下文章

Python--加密小练习

新手问题:Apache Shiro 恢复密码

(转)博客园登陆__JSEncrypt 分析

太极钱包_不一样的数字钱包

学生选课系统

Shiro学习——MD5加密与盐值