最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Shrio框架實(shí)現(xiàn)自定義密碼校驗(yàn)規(guī)則詳解

 更新時(shí)間:2026年03月14日 09:16:23   作者:陪妳去流浪丶  
文章主要介紹了Shiro框架的密碼校驗(yàn)機(jī)制,包括內(nèi)置的校驗(yàn)規(guī)則和自定義校驗(yàn)規(guī)則的實(shí)現(xiàn),在Shiro中,密碼校驗(yàn)主要通過自定義Realm來實(shí)現(xiàn),具體步驟包括定義用戶認(rèn)證信息和權(quán)限信息,并在CredentialsMatcher中實(shí)現(xiàn)用戶信息校驗(yàn)對(duì)比

shrio自己內(nèi)置一些密碼校驗(yàn)規(guī)則,也可以實(shí)現(xiàn)簡單的自定義,比如算法類型,hash次數(shù)等,但是有時(shí)候我們有一些比較特殊的密碼校驗(yàn)規(guī)則,需要自定義來實(shí)現(xiàn)

1.shiro的密碼校驗(yàn)是如何做的?

我們?cè)诘卿浄椒▋?nèi)做完參數(shù)校驗(yàn),驗(yàn)證碼匹配等基本工作之后,都會(huì)將用戶名和密碼通過subject.login(auth) 傳入框架來做用戶匹配,但是,是和什么地方的數(shù)據(jù)進(jìn)行匹配呢?

UsernamePasswordToken auth = new UsernamePasswordToken(username, password,false);
Subject subject = SecurityUtils.getSubject();
subject.login(auth);

答案就是在自定義的Realm中定義的AuthenticationInfo 進(jìn)行匹配

可以通過shiro框架源碼AuthenticatingRealm類的 assertCredentialsMatch方法看到,傳入了兩個(gè)參數(shù),token就是我們登陸方法中傳入的UsernamePasswordToken對(duì)象,而info就是我們?cè)卺斸斠籖ealm中doGetAuthenticationInfo 方法中定義的info對(duì)象。

shiro框架校驗(yàn):

//shiro源碼--用戶信息認(rèn)證 對(duì)比
 protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
        CredentialsMatcher cm = this.getCredentialsMatcher();
        if (cm != null) {
            //信息認(rèn)證
            if (!cm.doCredentialsMatch(token, info)) {
                String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
                throw new IncorrectCredentialsException(msg);
            }
        } else {
            throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify credentials during authentication.  If you do not wish for credentials to be examined, you can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
        }
    }

這里需要弄清楚 doGetAuthenticationInfo和doGetAuthorizationInfo  前者是定義用戶認(rèn)證信息的,而后者是定義用戶權(quán)限信息,有點(diǎn)容易混淆。

2.實(shí)現(xiàn)自定義Realm

public class ShiroFileRealm extends AuthorizingRealm implements InitializingBean {
	
	@Autowired
	public void setCredentialsDigest(CredentialsDigest credentialsDigest) {
		this.credentialsDigest = credentialsDigest;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		User user = userService.getUser(token.getUsername());
		if (user != null) {
            //此處返回的對(duì)象就是上面的info
			return new SimpleAuthenticationInfo(new ShiroUser(user.getUsername()), user.getPassword(),getName());
		}
		return null;
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		//自定義用戶權(quán)限
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		
		return info;
	}
	/**
	 * 設(shè)定密碼校驗(yàn)規(guī)則
	 */
	public void afterPropertiesSet() throws Exception {
		CredentialsMatcher matcher = new CredentialsMatcherAdapter(credentialsDigest);
		setCredentialsMatcher(matcher);
	}

}

上面代碼中SimpleAuthenticationInfo 就是返回的用戶認(rèn)證信息,也是框架中做對(duì)比的info

好了,認(rèn)證流程基本弄明白,我們就需要實(shí)現(xiàn)自定義校驗(yàn),怎么做呢?

3.實(shí)現(xiàn)自定義CredentialsMatcher 認(rèn)證類

/**
	 * 設(shè)定密碼校驗(yàn)規(guī)則
	 */
	public void afterPropertiesSet() throws Exception {
		CredentialsMatcher matcher = new CredentialsMatcherAdapter(credentialsDigest);
		//設(shè)置自定義的用戶信息認(rèn)證類
        setCredentialsMatcher(matcher);
	}

關(guān)鍵就是這里,CredentialsMatcherAdapter 是個(gè)實(shí)現(xiàn)了CredentialsMatcher接口的自定義類

public class CredentialsMatcherAdapter implements CredentialsMatcher {
    private CredentialsDigest credentialsDigest;

    public CredentialsMatcherAdapter(CredentialsDigest credentialsDigest) {
        Assert.notNull(credentialsDigest, "The argument must not be null");
        this.credentialsDigest = credentialsDigest;
    }

    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String plainCredentials, credentials;
        byte[] saltByte = null;
        plainCredentials = toStringCredentials(token.getCredentials());
        if (info instanceof SaltedAuthenticationInfo) {
            ByteSource salt = ((SaltedAuthenticationInfo) info).getCredentialsSalt();
            if (salt != null) saltByte = salt.getBytes();
        }
        credentials = toStringCredentials(info.getCredentials());
        if(saltByte != null){
            return credentialsDigest.matches(credentials, plainCredentials, saltByte);
        }
        return credentialsDigest.matches(credentials, plainCredentials);
    }

    private static String toStringCredentials(Object credentials) {
        if (credentials == null) {
            return null;
        } else if (credentials instanceof String) {
            return (String) credentials;
        } else if (credentials instanceof char[]) {
            return new String((char[]) credentials);
        } else {
            throw new IllegalArgumentException("credentials only support String or char[].");
        }
    }
}

doCredentialsMatch 方法就是實(shí)現(xiàn)用戶信息校驗(yàn) 對(duì)比的方法,上面shiro框架的校驗(yàn)流程(cm.doCredentialsMatch(token, info))就會(huì)走到我們這里的方法中

上面credentialsDigest.matches(credentials, plainCredentials); 是我自己實(shí)現(xiàn)的密碼比較方法

有加鹽模式和無鹽模式

貼出來給大家參考下

接口

public interface CredentialsDigest {
    String digest(String plainCredentials, byte[] salt);
    boolean matches(String credentials, String plainCredentials, byte[] salt);
    boolean matches(String credentials, String plainCredentials);
}

實(shí)現(xiàn)類

public  abstract class HashCredentialsDigest implements CredentialsDigest {
    static final int HASH_ITERATIONS = 1024;
    public String digest(String plainCredentials, byte[] salt) {
        if (StringUtils.isBlank(plainCredentials)) return null;
        byte[] hashPassword = digest(plainCredentials.getBytes(StandardCharsets.UTF_8), salt);
        return Hex.encodeHexString(hashPassword);
    }
    public boolean matches(String credentials, String plainCredentials, byte[] salt) {
        if (StringUtils.isBlank(credentials) && StringUtils.isBlank(plainCredentials)) return true;
        return StringUtils.equals(credentials, digest(plainCredentials, salt));
    }
    public boolean matches(String credentials, String plainCredentials) {
        if (StringUtils.isBlank(credentials) && StringUtils.isBlank(plainCredentials)) return true;
        return StringUtils.equals(credentials, plainCredentials);
    }
    protected abstract byte[] digest(byte[] input, byte[] salt);
}

主要的自定義代碼就在CredentialsMatcherAdapter和CredentialsDigest中。。。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 在Java8與Java7中HashMap源碼實(shí)現(xiàn)的對(duì)比

    在Java8與Java7中HashMap源碼實(shí)現(xiàn)的對(duì)比

    這篇文章主要介紹了在Java8與Java7中HashMap源碼實(shí)現(xiàn)的對(duì)比,內(nèi)容包括HashMap 的原理簡單介紹、結(jié)合源碼在Java7中是如何解決hash沖突的以及優(yōu)缺點(diǎn),結(jié)合源碼以及在Java8中如何解決hash沖突,balance tree相關(guān)源碼介紹,需要的朋友可以參考借鑒。
    2017-01-01
  • IDEA實(shí)現(xiàn)純java項(xiàng)目并打包jar的步驟(不使用Maven,Spring)

    IDEA實(shí)現(xiàn)純java項(xiàng)目并打包jar的步驟(不使用Maven,Spring)

    在Java開發(fā)中我們通常會(huì)將我們的項(xiàng)目打包成可執(zhí)行的Jar包,以便于在其他環(huán)境中部署和運(yùn)行,這篇文章主要介紹了IDEA實(shí)現(xiàn)純java項(xiàng)目并打包jar(不使用Maven,Spring)的相關(guān)資料,需要的朋友可以參考下
    2025-08-08
  • Matlab及Java實(shí)現(xiàn)小時(shí)鐘效果

    Matlab及Java實(shí)現(xiàn)小時(shí)鐘效果

    這篇文章主要為大家詳細(xì)介紹了Matlab及Java實(shí)現(xiàn)小時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • Java自帶的Http?Server實(shí)現(xiàn)設(shè)置返回值的類型(content-type)

    Java自帶的Http?Server實(shí)現(xiàn)設(shè)置返回值的類型(content-type)

    這篇文章主要介紹了Java自帶的Http?Server實(shí)現(xiàn)設(shè)置返回值的類型(content-type),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • java實(shí)現(xiàn)猜數(shù)字游戲

    java實(shí)現(xiàn)猜數(shù)字游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)猜數(shù)字游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • IDEA創(chuàng)建parent項(xiàng)目(聚合項(xiàng)目)

    IDEA創(chuàng)建parent項(xiàng)目(聚合項(xiàng)目)

    這篇文章主要介紹了IDEA創(chuàng)建parent項(xiàng)目(聚合項(xiàng)目),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • SpringBoot 利用RestTemplate http測(cè)試

    SpringBoot 利用RestTemplate http測(cè)試

    這篇文章主要介紹了SpringBoot 利用RestTemplate http測(cè)試,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java使用zookeeper實(shí)現(xiàn)的分布式鎖示例

    java使用zookeeper實(shí)現(xiàn)的分布式鎖示例

    這篇文章主要介紹了java使用zookeeper實(shí)現(xiàn)的分布式鎖示例,需要的朋友可以參考下
    2014-05-05
  • 使用okhttp替換Feign默認(rèn)Client的操作

    使用okhttp替換Feign默認(rèn)Client的操作

    這篇文章主要介紹了使用okhttp替換Feign默認(rèn)Client的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Mybatis關(guān)聯(lián)映射的實(shí)現(xiàn)

    Mybatis關(guān)聯(lián)映射的實(shí)現(xiàn)

    本文介紹了MyBatis關(guān)聯(lián)映射的實(shí)現(xiàn)方式,直接查詢和分步查詢,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-12-12

最新評(píng)論

海晏县| 文山县| 天水市| 抚州市| 炉霍县| 保山市| 武陟县| 临沂市| 全椒县| 平山县| 北京市| 崇阳县| 明光市| 色达县| 平舆县| 明星| 横峰县| 太和县| 屏南县| 陵水| 彰武县| 哈巴河县| 巴青县| 澳门| 威海市| 乐业县| 萨迦县| 马边| 寻甸| 陇川县| 西盟| 宝兴县| 张家口市| 沽源县| 宣城市| 潮州市| 进贤县| 上蔡县| 宁乡县| 庆安县| 德江县|