- 既然是多Realm,我们需要在每个Realm中重写Support方法
//UserRealm 自身验证
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken;
}
//SSO 单点登录验证
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof OAuth2SsoAuthenticationToken;
}
- 自定义一个类继承 ModularRealmAuthenticator,并重写doMultiRealmAuthentication方法
/**
* @author yafengliang@yeah.net
* @Description
* @date 2022-08-18 9:18
*/
public class MultiRealmAuthenticator extends ModularRealmAuthenticator {
private static final Logger log = LoggerFactory.getLogger(ModularRealmAuthenticator.class);
@Override
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
AuthenticationStrategy strategy = getAuthenticationStrategy();
AuthenticationInfo authentication = strategy.beforeAllAttempts(realms, token);
if (log.isTraceEnabled()) {
log.trace("Iterating through {} realms for PAM authentication", realms.size());
}
AuthenticationException authenticationException = null;
for (Realm realm : realms) {
authentication = strategy.beforeAttempt(realm, token, authentication);
if (realm.supports(token)) {
log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);
AuthenticationInfo info = null;
try {
info = realm.getAuthenticationInfo(token);
//因为默认使用的是AtLeastOneSuccessfulStrategy(),有一个Realm成功就可以
authenticationException = null;
} catch (AuthenticationException e) {
authenticationException = e;
if (log.isDebugEnabled()) {
String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";
log.debug(msg, e);
}
}
authentication = strategy.afterAttempt(realm, token, info, authentication, authenticationException);
} else {
log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
}
}
if (authenticationException != null) {
throw authenticationException;
}
authentication = strategy.afterAllAttempts(token, authentication);
return authentication;
}
}
- 在shiro的配置类中注入自定义类
@Bean
public AbstractAuthenticator authenticator(UserRealm userRealm, OAuth2Realm oAuth2Realm){
ModularRealmAuthenticator authenticator = new MultiRealmAuthenticator();
authenticator.setRealms(Arrays.asList(userRealm,oAuth2Realm));
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return authenticator;
}
- 在securityManager中加入多realm
/**
* 安全管理器
*/
@Bean
public SecurityManager securityManager(UserRealm userRealm, OAuth2Realm oAuth2Realm,AbstractAuthenticator authenticator) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
// securityManager.setRealm(userRealm);
securityManager.setRealms(Arrays.asList(userRealm, oAuth2Realm));
// 注入缓存管理器;
securityManager.setCacheManager(getEhCacheManager());
// session管理器
securityManager.setSessionManager(sessionManager());
//解决多realm的异常问题重点在此
securityManager.setAuthenticator(authenticator);
return securityManager;
}
- 再次运行解决
感谢 https://blog.csdn.net/qq_46416934/article/details/124021822
感谢 https://blog.csdn.net/m0_67403188/article/details/124019651