Shiro——MD5加密


一、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) 構造器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM