Shiro getAuthenticationInfo()中抛出异常, 全局异常处理却收不到自己抛出的异常

当Shiro在getAuthenticationInfo()中抛出异常时,全局异常处理无法捕获。原因是默认的AuthenticationStrategy导致。解决方案是实现自定义AuthenticationStrategy并正确配置。尝试通过Spring Boot YAML配置、shiro.ini配置、创建Bean方式失败。最终,通过获取SecurityManager的Authenticator并设置自定义Strategy成功解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该解决思路来自StackOverflow: Apache Shiro: Exception-Handling with Multiple Realms

首先下结论: 这是因为使用了默认的AuthenticationStrategy所致, 只需要为自己的shiro实现自定义的AuthenticationStrategy, 并将其正确配置即可.

public class MyAtLeastOneSuccessfulStrategy extends AtLeastOneSuccessfulStrategy {
   
   
    @Override
    public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
   
   
        if (t != null && t instanceof AuthenticationException){
   
   
            throw (AuthenticationException) t;
        }
        return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
    }
}

配置AuthenticationStrategy的方法如下:

MyAtLeastOneSuccessfulStrategy strategy = new MyAtLeastOneSuccessfulStrategy();
((ModularRealmAuthenticator)(securityManager.getAuthenticator()))
														.setAuthenticationStrategy(strategy);

如果希望知道为何收到的是AuthenticationException, 以及为何要按照上面这么配置. 请看源码分析(我的经历):

为何总是收不到自己throw的异常

doGetAuthenticationInfo方法中

if (user == null)
            throw new UnknownAccountException("账户不存在!");

在调用一堆构造函数后, 进入ModularRealmAuthenticator的doMultiRealmAuthentication方法

protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, 
                        AuthenticationToken token) {
   
   
				
				// 获取验证策略
        AuthenticationStrategy strategy = getAuthenticationStrategy();

        AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
				// 日志
        if (log.isTraceEnabled()) {
   
   
            log.trace("Iterating through {} realms for PAM authentication", realms.size());
        }
				
				// 循环遍历realm
        for (Realm realm : realms) {
   
   
						// 
            try {
   
   
                aggregate = strategy.beforeAttempt(realm, token, aggregate);
            } catch (ShortCircuitIterationException shortCircuitSignal) {
   
   
                // Break from continuing with subsequnet realms on receiving 
                // short circuit signal from strategy
                break;
            }

            if (realm.supports(token)) {
   
   

                log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);

                AuthenticationInfo info = null;
                Throwable t = null;
                try {
   
   
										**// 这里调用了自定义Realm的getAuthenticationInfo方法**
                    **info = realm.getAuthenticationInfo(token);**
                } catch (Throwable throwable) {
   
   
										**// 这里采用catch将Realm中抛出的异常直接捕获, 
										// 并且在后续的处理中并没有将该异常重新抛出**
                    t = throwable;
                    if (log.isDebugEnabled()) {
   
   
                        String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";
                        log.debug(msg, t);
                    }
                }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值