Shiro——MD5加密

混江龙づ霸主 提交于 2019-12-24 17:56:12

一、shiro默认密码的比对

通过 AuthenticatingRealm credentialsMatcher 属性来进行的密码的比对

/**源码org.apache.shiro.realm.AuthenticatingRealm
* Asserts that the submitted {@code AuthenticationToken}'s credentials match the stored account
* {@code AuthenticationInfo}'s credentials, and if not, throws an {@link AuthenticationException}.
*
* @param token the submitted authentication token
* @param info  the AuthenticationInfo corresponding to the given {@code token}
* @throws AuthenticationException if the token's credentials do not match the stored account credentials.
*/
    protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)     throws AuthenticationException {
        CredentialsMatcher cm = getCredentialsMatcher();
        if (cm != null) {
            if (!cm.doCredentialsMatch(token, info)) {
                //not successful - throw an exception to indicate this:
                String msg = "";
                throw new IncorrectCredentialsException(msg);
            }
        } else {
            throw new AuthenticationException("");
        }
    }

调试技巧:在org.apache.shiro.authc.UsernamePasswordToken的getPassword()方法中添加断点

①、接口CredentialsMatcher

源码
package org.apache.shiro.authc.credential;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;

public interface CredentialsMatcher {

    boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info);

}

②、接口CredentialsMatcher的继承关系

 shiro默认是用org.apache.shiro.authc.credential.SimpleCredentialsMatcher进行密码比较

//SimpleCredentialsMatcher.doCredentialsMatch()public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        Object tokenCredentials = getCredentials(token);
        Object accountCredentials = getCredentials(info);
        return equals(tokenCredentials, accountCredentials);
    }

二、MD5加密

使用 new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations) 来计算盐值加密后的密码的值

import org.apache.shiro.crypto.hash.SimpleHash;import org.apache.shiro.util.ByteSource;
public static void  main(String[] args){
        //加密方式
        String hashAlgorithmName = "MD5";
        //明文密码
        Object credentials = "1234";
        //盐值
        Object salt = ByteSource.Util.bytes("nchu");
        int hashIterations = 1024;

        Object result = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);     //加密后的密码
        System.out.println(result);
    }

三、Shiro密码加密

①、在spring核心配置文件中配置自定义Realm

    <!-- 自定义Realm -->
    <bean id="MD5Realm" class="com.nchu.shiro.MD5Realm">
       <!-- 更改自定义Realm的默认credentialsMatcher属性-->
        <property name="credentialsMatcher" >
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <!--指定加密算法-->
                <property name="hashAlgorithmName" value="MD5"></property>
                <!--设置加密次数-->
                <property name="hashIterations" value="1024"></property>
            </bean>
        </property>
    </bean>
    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realms">
            <list>
                <ref bean="MD5Realm"/>
            </list>
        </property>
    </bean>

替换当前 Realm 的 credentialsMatcher 属性. 直接使用 HashedCredentialsMatcher 对象, 并设置加密算法即可

②、自定义Realm

使用shiro MD5加密前提数据库存储的密码是经过MD5加密的

import com.nchu.mvc.dao.ShiroRealmMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Created by yangshijing on 2018/1/16 0016.
 */
public class MD5Realm extends AuthenticatingRealm {
    @Autowired
    ShiroRealmMapper shiroRealmMapper;
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("----->"+token.hashCode());
        //1. 把 AuthenticationToken 转换为 UsernamePasswordToken
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        //2. 从 UsernamePasswordToken 中来获取 username
        String username = upToken.getUsername();

        //3. 调用数据库的方法, 从数据库中查询 username 对应的用户记录

        System.out.println("从数据库中获取 username: " + username + " 所对应的用户信息.");
        String password  = shiroRealmMapper.login(username);
        //4. 若用户不存在, 则可以抛出 UnknownAccountException 异常
        if(password==null){
            throw new UnknownAccountException("用户不存在!");
        }

        //5. 根据用户信息的情况, 决定是否需要抛出其他的 AuthenticationException 异常.
        /*  if("monster".equals(username)){
            throw new LockedAccountException("用户被锁定");
        }*/
        //6. 根据用户的情况, 来构建 AuthenticationInfo 对象并返回.      //通常使用的实现类为: SimpleAuthenticationInfo
        //以下信息是从数据库中获取的.
        //1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象.
        Object principal = username;
        //2). hashedCredentials: 加密后的密码.
        Object hashedCredentials = password;
        //3). realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可
        String realmName = getName();
        //4). 加密盐值
        ByteSource credentialsSalt = ByteSource.Util.bytes("nchu");
        SimpleAuthenticationInfo info = //new SimpleAuthenticationInfo(principal, credentials, realmName);
        new SimpleAuthenticationInfo(principal,hashedCredentials,credentialsSalt,realmName);
        return info;
    }

注意:在 doGetAuthenticationInfo 方法返回值创建 SimpleAuthenticationInfo 对象的时候, 需要使用SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName) 构造器

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!