ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Shiro中md5加密--散列算法(转)

2021-12-25 16:36:28  阅读:184  来源: 互联网

标签:users -- salt Shiro import password 散列 shiro md5


认识md5

md5是一种加密算法,保护数据安全(现被证实并不怎么安全),shiro中提供了md5加密算法
salt表示加盐,通过加盐的方式能够进一步提高数据的安全性,所以在数据库users表设计的时候,除了id、username、password之外,还有一列password_salt

 

//md5加密
        Md5Hash hash=new Md5Hash("123");
        System.out.println(hash.toString());
        //md5加盐
        hash=new Md5Hash("123","wit");
        System.out.println(hash.toString());
        //md5加盐 散列两次,散列次数越多,密码越安全
        hash=new Md5Hash("123","wit",2);
        System.out.println(hash.toString());
        hash=new Md5Hash("456","wit",2);
        System.out.println(hash.toString());

 

使用md5呢,首先要保证数据库中的密码是(已经用工具)加密过的

自定义的realm

从数据库拿到数据user(id、username、password、password_salt)对象后,下边这行代码传给shiro,shiro就知道需要数据是加密过的,还有一些参数,比如散列次数,加密方式,就需要对realm进行配置

 

SimpleAuthenticationInfo(username,password,ByteSource.Util.bytes(salt),getName());
package cn.wit.realm;

import java.beans.PropertyVetoException;
import java.sql.ResultSet;
import java.sql.SQLException;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import cn.wit.users.Users;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;

public class UserRealm extends AuthorizingRealm{
    @Override
    public String getName() {
        // TODO Auto-generated method stub
        return "uesrRealm";
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken taken) throws AuthenticationException {
            String username=(String) taken.getPrincipal();
            Users users=null;
            Connection conn=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            ComboPooledDataSource cpds=null;
            try {
              //c3p0获取数据库连接conn
                cpds= new ComboPooledDataSource();
                cpds.setDriverClass("com.mysql.jdbc.Driver");
                cpds.setJdbcUrl("jdbc:mysql://localhost:3306/login");
                cpds.setUser("root");
                cpds.setPassword("wityy");
                conn = cpds.getConnection();
                
                String sql="select *from users where username=?";
                ps= conn.prepareStatement(sql);
                ps.setObject(1,username);
                rs=ps.executeQuery();
                while(rs.next()){
                    users=new Users();
                    users.setId(rs.getInt("id"));
                    users.setUsername(rs.getString("username"));
                    users.setPassword(rs.getString("password"));
                    users.setPassword_salt(rs.getString("password_salt"));
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (PropertyVetoException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                try {
                    if(rs!=null){
                        rs.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                try {
                    if(ps!=null){
                        ps.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                try {
                    if(conn!=null){
                        conn.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        
          username=users.getUsername();
          String password=users.getPassword();
          String salt=users.getPassword_salt();
          System.out.println(username);
          System.out.println(password);
          System.out.println(salt);
          //从数据库中拿到的密码是经过加密的(并且加了盐),所以数据库中才设计盐这个属性,想要解密不仅要拿到密码,还要从数据库拿到盐
          //除此之外,需要设置realm 告知shiro需要用md5的方式进行解密
          SimpleAuthenticationInfo info=new 
                  SimpleAuthenticationInfo(username,password,ByteSource.Util.bytes(salt),getName());
        
        return info;
    }

    
}

ini

hashAlgorithmName表示加密方式,hashIterations表示散列次数,credentialsMatcher是关于设置加密的类,将其赋值给realm。

[main]
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=2

userRealm=cn.wit.realm.UserRealm
userRealm.credentialsMatcher=$credentialsMatcher
securityManager.realm=$userRealm
public class Authentication {
    public static void main(String[] args) {
        //拿到SecurityManager并将它放到环境当中
        Factory<SecurityManager>factory=new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        
        //拿到subject接口
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken taken=new UsernamePasswordToken("zhangsan","123");
        try {
            if(taken!=null){
                subject.login(taken);
            }
            if(subject.isAuthenticated()){
                System.out.println("登录成功");
            }
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("账号或密码错误");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("账号或密码错误");
        }
        
        
    }
}

md5源码跟踪

从login进入源码,subject实现类DelegatingSubject,将自己和taken都给了SecurityManager,实现类为DefaultSecurityManager,该类login方法调用Authenticator的Authenticate方法,进入Authenticator,实现类为ModularRealmAuthenticator,里边有setRealms、setAuthenticationStrategy,可以进行 认证策略和realms的设置,进入Realm接口,在它的实现类AuthenticatingRealm里面有credentialsMatcher属性,表示加密
在这里插入图片描述
查看类层次,下边有不同的解密方式的实现类,

在这里插入图片描述
这些加密的方式都是继承的HashedCredentialsMatcher,下边的这个类的set方法,我们在ini中设置的正是这些属性,出于对salt信息的保护,所以设置ini只设置了加密方式和散列次数,将salt在自定义的realm中跟账号密码一起传递给shiro
在这里插入图片描述

 

标签:users,--,salt,Shiro,import,password,散列,shiro,md5
来源: https://www.cnblogs.com/fcajchd/p/15730844.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有