《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
首先,我们先看Realm是怎么被执行的
Realm是被一个名叫ModularRealmAuthenticator的类执行的
具体细节如下
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
//检验是否有Realm
this.assertRealmsConfigured();
//获取所有的Realm
Collection realms = this.getRealms();
//如果Realm只有1个,就只执行那一个,如果Realm有多个,全部都要执行
return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken);
}
Shiro自带的UserNamePasswordToken感觉不太够用,因为下面我们要根据Token自带的属性进行区分,所以下面需要扩展UserNamePasswordToken。
/**
-
@Author: Ember
-
@Date: 2021/4/26 17:30
-
@Description:
*/
public class Token extends UsernamePasswordToken {
/**
- 用来判断执行哪个Realm
**/
private String loginType;
public Token(String username, String password, String loginType) {
super(username, password);
this.loginType = loginType;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
}
我们从上面可以看到,Realm的执行是跟ModularRealmAuthenticator密切相关的,所以我们要想改变Realm的执行,就必须扩展ModularRealmAuthenticator,然后重写doAuthenticate方法,最后装配上我们自定义的ModularRealmAuthenticator即可。
我们可以通过参考上面的源代码进行对应重写,本质上只是改变realms集合即可,即将想要执行的realm放到新的realms集合里面,执行该realms集合即可
具体扩展如下
/**
-
@Author: Ember
-
@Date: 2021/4/26 17:36
-
@Description:
*/
public class MyDiyModularRealmAuthenticator extends ModularRealmAuthenticator {
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
Token token = (Token) authenticationToken;
//判断是否有Realm装配
this.assertRealmsConfigured();
Collection realms = getRealms();
//如果不唯一,分类进行
Collection waitChooseRealms = new ArrayList<>();
for (Realm realm : realms) {
//遍历所有Realm
//通过获取Realm的名字,比较token的信息,将想要执行的Realm放到新的Realms组合里面
if(realm.getName().contains(token.getLoginType())){
waitChooseRealms.add(realm);
}
}
//与源码一样,如果只有一个,就执行一个
if (realms.size() == 1){
return doSingleRealmAuthentication((Realm)waitChooseRealms.iterator().next(), token);
}
//与源码一样,如果有多个,就将整个Realms数组放进去
return doMultiRealmAuthentication(waitChooseRealms,token);
}
}
我自定义的ModularRealmAuthentic是根据Realm的名字来进行区分的,所以,Realm的名字最后不要出现相同的关键字符串,比如下面我要创一个user、manager和merchant的Realm,那么就不可以出现usermerchant这样的Realm。否则,即会进行userRealm,也会进行merchantRealm。
UserRealm
这是原有的
/**
-
@Author: Ember
-
@Date: 2021/4/26 17:36
-
@Description:
*/
public class MyDiyModularRealmAuthenticator extends ModularRealmAuthenticator {
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
Token token = (Token) authenticationToken;
//判断是否有Realm装配
this.assertRealmsConfigured();
Collection realms = getRealms();
//如果不唯一,分类进行
Collection waitChooseRealms = new ArrayList<>();
for (Realm realm : realms) {
if(realm.getName().contains(token.getLoginType())){
waitChooseRealms.add(realm);
}
}
if (realms.size() == 1){
return doSingleRealmAuthentication((Realm)waitChooseRealms.iterator().next(), token);
}
return doMultiRealmAuthentication(waitChooseRealms,token);
}
}
ManagerRealm和MerchantRealm
这两个Realm只做测试使用,所以就不详细做认证和授权操作了
/**
-
@Author: Ember
-
@Date: 2021/4/26 17:47
-
@Description:
*/
public class ManagerRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println(“=进入了ManagerRealm===”);
return null;
}
}
/**
-
@Author: Ember
-
@Date: 2021/4/26 17:49
-
@Description:
*/
public class MerchantRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println(“=进入了MerchantRealm===”);
return null;
}
}
因为自定义了多个Realm,还有ModularRealmAuthentic,所以这些我们都要装配上
/**
-
@Author: Ember
-
@Date: 2021/4/2 18:05
-
@Description: ShiroConfig
*/
@Configuration
public class MyShiroConfig{
/**
-
ShiroFactoryBean装配安全管理
-
@param defaultSecurityManager
-
@return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager defaultSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//这里要让ThredContext对defaultSecurityManager绑定,否则会报错
ThreadContext.bind(defaultSecurityManager);
shiroFilterFactoryBean.setSecurityManager(defaultSecurityManager);
return shiroFilterFactoryBean;
}
/**
-
安全管理装配Realm
-
@param realm
-
@return
*/
@Bean
public DefaultSecurityManager defaultSecurityManager(
@Qualifier(“myRealm”) MyUserRealm realm,
@Qualifier(“MerchantRealm”) MerchantRealm merchantRealm,
@Qualifier(“ManagerRealm”) ManagerRealm managerRealm,
@Qualifier(“authenticator”) MyDiyModularRealmAuthenticator authenticator){
//注意这里要是DefaultWebSecurityManager,否则报错
DefaultSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setAuthenticator(authenticator);
//装配上Realm
Collection realms = new ArrayList();
realms.add(realm);
realms.add(merchantRealm);
realms.add(managerRealm);
//securityManager.setRealm(realm);
// securityManager.setRealm(merchantRealm);
securityManager.setRealms(realms);
return securityManager;
}
/**
最后
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
realms = new ArrayList();
realms.add(realm);
realms.add(merchantRealm);
realms.add(managerRealm);
//securityManager.setRealm(realm);
// securityManager.setRealm(merchantRealm);
securityManager.setRealms(realms);
return securityManager;
}
/**
最后
[外链图片转存中…(img-2G9oimAx-1714759421415)]
[外链图片转存中…(img-dJEJV3S5-1714759421416)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!