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

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

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

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

1.shiro的密碼校驗是如何做的?

我們在登錄方法內(nèi)做完參數(shù)校驗,驗證碼匹配等基本工作之后,都會將用戶名和密碼通過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方法看到,傳入了兩個參數(shù),token就是我們登陸方法中傳入的UsernamePasswordToken對象,而info就是我們在釘釘一Realm中doGetAuthenticationInfo 方法中定義的info對象。

shiro框架校驗:

//shiro源碼--用戶信息認(rèn)證 對比
 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.實現(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) {
            //此處返回的對象就是上面的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è)定密碼校驗規(guī)則
	 */
	public void afterPropertiesSet() throws Exception {
		CredentialsMatcher matcher = new CredentialsMatcherAdapter(credentialsDigest);
		setCredentialsMatcher(matcher);
	}

}

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

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

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

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

關(guān)鍵就是這里,CredentialsMatcherAdapter 是個實現(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 方法就是實現(xiàn)用戶信息校驗 對比的方法,上面shiro框架的校驗流程(cm.doCredentialsMatch(token, info))就會走到我們這里的方法中

上面credentialsDigest.matches(credentials, plainCredentials); 是我自己實現(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);
}

實現(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é)

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

    SpringBoot 利用RestTemplate http測試

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

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

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

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

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

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

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

最新評論

双城市| 绥阳县| 井陉县| 鹰潭市| 浦城县| 阳原县| 工布江达县| 保定市| 伊宁市| 堆龙德庆县| 辉县市| 宁波市| 普格县| 安溪县| 紫云| 中阳县| 错那县| 兴化市| 浮山县| 汪清县| 宁海县| 界首市| 茌平县| 佳木斯市| 印江| 确山县| 五常市| 普定县| 石门县| 华亭县| 肇州县| 建湖县| 夏河县| 靖远县| 邵东县| 七台河市| 上高县| 民县| 安吉县| 枣阳市| 安吉县|