Shiro多个Realm认证及授权
解决方案如下:
首先自定义一个DefaultUsernamepasswordToken.java,继承Shiro自带的UsernamePasswordToken,在DefaultUsernamepasswordToken中新加一个属性
private String loginType; 而后生成getter setter;
public class DefaultUsernamepasswordToken extends UsernamePasswordToken { /** * 判断登录类型 */ private String loginType; public String getLoginType() { return this.loginType; } public void setLoginType(String loginType) { this.loginType = loginType; } /** * Shiro 构造方法 * * @author : tanzhen * @date :2016年7月28日 */ public DefaultUsernamepasswordToken(String username, String password) { super(username, password); } public DefaultUsernamepasswordToken() { } }
然后自定义一个DefautModularRealm.java,继承 ModularRealmAuthenticator,重写doMultiRealmAuthentication、doSingleRealmAuthentication、doAuthenticate、assertRealmsConfigured四个方法,还需要定义一个变量,
用来接收传进来的多个Realm。
public class DefaultModularRealm extends ModularRealmAuthenticator { private Map<String, Object> definedRealms; /** * 多个realm实现 */ @Override protected AuthenticationInfo doMultiRealmAuthentication( Collection<Realm> realms, AuthenticationToken token) { return super.doMultiRealmAuthentication(realms, token); } /** * 调用单个realm执行操作 */ @Override protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) { // 如果该realms不支持(不能验证)当前token if (!realm.supports(token)) { throw new ShiroException("token错误!"); } AuthenticationInfo info = null; try { info = realm.getAuthenticationInfo(token); if (info == null) { throw new ShiroException("token不存在!"); } } catch (Exception e) { throw new ShiroException("用户名或者密码错误!"); } return info; } /** * 判断登录类型执行操作 */ @Override protected AuthenticationInfo doAuthenticate( AuthenticationToken authenticationToken) throws AuthenticationException { this.assertRealmsConfigured(); Realm realm = null; DefaultUsernamepasswordToken token = (DefaultUsernamepasswordToken) authenticationToken; if (token.getLoginType().equals("huimai")) { realm = (Realm) this.definedRealms.get("defaultJdbcRealm"); } if (token.getLoginType().equals("shiro")) { realm = (Realm) this.definedRealms.get("shiroDbRealm"); } if (realm == null) { return null; } return this.doSingleRealmAuthentication(realm, authenticationToken); } /** * 判断realm是否为空 */ @Override protected void assertRealmsConfigured() throws IllegalStateException { this.definedRealms = this.getDefinedRealms(); if (CollectionUtils.isEmpty(this.definedRealms)) { throw new ShiroException("值传递错误!"); } } public Map<String, Object> getDefinedRealms() { return this.definedRealms; } public void setDefinedRealms(Map<String, Object> definedRealms) { this.definedRealms = definedRealms; } }
这里需要注意是 其实 流程是:在给DefaultUsernamepasswordToken赋值时,将loginType设置成相应的参数,然后在doAuthenticate时判断,单个调用对应的Realm。然后是xml文件配置:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 其他配置 --> <property name="authenticator" ref="defineModularRealmAuthenticator" /> <property name="realms"> <list> <ref bean="defaultJdbcRealm" /> <ref bean="shiroDbRealm" /> </list> </property> </bean> <!-- --> <bean id="defineModularRealmAuthenticator" class="com.zynsun.platform.realm.DefaultModularRealm"> <property name="definedRealms"> <map> <entry key="defaultJdbcRealm" value-ref="defaultJdbcRealm" /> <entry key="shiroDbRealm" value-ref="shiroDbRealm" /> </map> </property> <!-- <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy" /> </property> --> </bean> <!-- --> <bean id="defaultJdbcRealm" class="com.xxxx.shiro.DefaultRealm"> </bean> <bean id="shiroDbRealm" class="com.xxx.shiro.ShiroRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"></property> </bean>
利用SecurityManager来进行配置。这样就完成了多个Realm认证,其实这种也只能算是单个Realm,毕竟是多个分割成单个去校验,还请大家多多指教。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: Shiro登录验证实例详解与源码
- 下一篇: 如何利用PHP来截取一段中文字符串而不出现乱码