NutzCN Logo
问答 nutzwk 权限各组件对应关系
发布于 2618天前 作者 menglinxi 1810 次浏览 复制 上一个帖子 下一个帖子
标签: nutzwk

shiro.ini

shiroDbRealm = cn.wizzer.common.shiro.realm.NutDaoRealm
shiroDbRealm.credentialsMatcher = $sha256Matcher

authc = cn.wizzer.common.shiro.filter.SimpleAuthenticationFilter
authc.loginUrl = /platform/login
logout.redirectUrl = /platform/login

[urls]
/platform/doLogin = anon
/assets/** = anon
/** = anon
/platform/** = authc

动态链

var chain={
	"default" : {
		"ps" : [
			  "cn.wizzer.common.processor.LogTimeProcessor",
			  "cn.wizzer.common.processor.GlobalsSettingProcessor",
			  "org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor",
		      "org.nutz.mvc.impl.processor.EncodingProcessor",
		      "org.nutz.mvc.impl.processor.ModuleProcessor",
              "cn.wizzer.common.processor.NutShiroProcessor",
              "cn.wizzer.common.processor.XssSqlFilterProcessor",
		      "org.nutz.mvc.impl.processor.ActionFiltersProcessor",
		      "org.nutz.mvc.impl.processor.AdaptorProcessor",
		      "org.nutz.mvc.impl.processor.MethodInvokeProcessor",
			  "org.nutz.mvc.impl.processor.ViewProcessor"
		],
		"error" : 'org.nutz.mvc.impl.processor.FailProcessor'
	}
};

系统登录

 @At("/doLogin")
    @Ok("json")
    @Filters(@By(type = AuthenticationFilter.class))
    public Object doLogin(@Attr("loginToken") AuthenticationToken token, HttpServletRequest req, HttpSession session) {
        int errCount = 0;
}

以上配置,请求逻辑从 [urls]开始,/platform/路径的请求,除了 dologin,不做拦截之外,其他都通过SimpleAuthenticationFilter拦截,并通过,shiroDbRealm处理权限相关,动态连中的 cn.wizzer.common.processor.NutShiroProcessor,怎么和 SimpleAuthenticationFilter 并联起来?系统登录 AuthenticationFilter,这个filter,跟NutShiroProcessor,怎么对应?
再有一套权限体系,shiro.ini,需要怎么配置,怎么通过,自定义processor处理?

8 回复

先说几个事实哦:

  1. NutShiroProcessor负责处理入口方法的shiro注解.
  2. SimpleAuthenticationFilter 不处理登录请求

首先, 请求通过SimpleAuthenticationFilter 时,它只按shiro.ini中的urls配置,判断是否已经登录, 跟NutShiroProcessor无交集. 由于只涉及登录与否, 所以与realm也没有交集.

然后 请求经过NutShiroProcessor时, 如果存在shiro的注解, 那么通过shiro的aop机制, 调用subject.isPermitted等方法判断权限,判断权限的过程中,shiro内部会调用shiroDbRealm获取权限列表

真正的登录请求是由入口方法处理的, 在入口方法内生成token, 然后调用subject.login进行登录. 这样的好处是, 可以完全控制返回值, 按需要返回不同的结果, 如果这一步放在AuthenticationFilter(例如FormAuthenticationFilter)里面做,就极其蛋疼.

如果前台要做一套登录,权限,需要和后台独立。SimpleAuthenticationFilter ,这个需要重新写吗?

不需要, 登录是在入口方法里面做的, 跟SimpleAuthenticationFilter没有关系.

真正的登录请求是由入口方法处理的, 在入口方法内生成token, 然后调用subject.login进行登录,这个登录和Realm怎么对应起来?如果有两个 realm,无法知道,前台登录会走哪个realm。

我定义了两个,FontAuthenticationFilter,PlatformAuthenticationFilter filter,一个处理前台登录,一个处理后台登录。两个 realm,FontAuthorizingRealm,PlatformAuthorizingRealm,但是,我不想登陆的时候,同时验证前台权限和后台权限,不论从哪里登录,前台路径过来的登录只能走前台验证,后台登录,只能走后台登录。
我写了个 DefautModularRealm extends org.apache.shiro.authc.pam.ModularRealmAuthenticator 来决定 realm的走向。

package cn.wizzer.app.web.commons.shiro.realm;

import cn.wizzer.framework.shiro.token.CaptchaToken;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.realm.Realm;
import org.nutz.ioc.loader.annotation.Inject;

/**
 * Created by Administrator on 2017-02-23.
 */
public class DefautModularRealm extends org.apache.shiro.authc.pam.ModularRealmAuthenticator {

    @Inject
    FontAuthorizingRealm fontAuthorizingRealm;
    @Inject
    PlatformAuthorizingRealm platformAuthorizingRealm;
    /**
     * 调用单个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 token)throws AuthenticationException {
        this.assertRealmsConfigured();
        Realm realm = null;
        CaptchaToken authcToken = (CaptchaToken) token;
        //判断是否是后台用户
        if (authcToken.getUsertype()==1) {
            realm = (Realm) this.fontAuthorizingRealm;
        }
        else{
            realm = (Realm) this.platformAuthorizingRealm;
        }

        return this.doSingleRealmAuthentication(realm, authcToken);
    }

}

shiro.ini配置如下:

[main]
# cacheManager
cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml

;-------------Redis作为shiro二级缓存时启用这里---------
;jedisAgent = org.nutz.integration.jedis.JedisAgent
;cacheManager_ehcache = org.apache.shiro.cache.ehcache.EhCacheManager
;cacheManager_ehcache.cacheManagerConfigFile=classpath:ehcache.xml
;cacheManager_redis = org.nutz.plugins.cache.impl.redis.RedisCacheManager
;cacheManager_redis.mode=kv
;cacheManager_redis.debug=true
;cacheManager = org.nutz.plugins.cache.impl.lcache.LCacheManager
;cacheManager.jedisAgent = $jedisAgent
;cacheManager.level1 = $cacheManager_ehcache
;cacheManager.level2 = $cacheManager_redis
;-------------Redis作为shiro二级缓存时启用这里---------

# Session
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.sessionValidationSchedulerEnabled = false

# Session Cache
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionDAO.cacheManager = $cacheManager
sessionDAO.activeSessionsCacheName = shiro-activeSessionCache
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager

# Cookie
sessionIdCookie = org.apache.shiro.web.servlet.SimpleCookie
sessionIdCookie.name = sid
#sessionIdCookie.domain=wizzer.cn
#sessionIdCookie.path=
sessionIdCookie.maxAge = 946080000
sessionIdCookie.httpOnly = true
sessionManager.sessionIdCookie = $sessionIdCookie
sessionManager.sessionIdCookieEnabled = true
sessionManager.globalSessionTimeout = 3600000

#bak...
#sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager
#sessionListener1 = cn.wizzer.common.shiro.listener.MySessionListener
#sessionManager.sessionListeners = $sessionListener1
#sessionManager.globalSessionTimeout=50000
#securityManager.sessionManager=$sessionManager

rememberMeCookie = org.apache.shiro.web.servlet.SimpleCookie
rememberMeCookie.name = remember
rememberMeCookie.maxAge = 604800
rememberMeCookie.httpOnly = true
rememberMeManager = cn.wizzer.framework.shiro.remember.LightCookieRememberMeManager
rememberMeManager.cookie = $rememberMeCookie

sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
sha256Matcher.storedCredentialsHexEncoded = false
sha256Matcher.hashIterations = 1024
sha256Matcher.hashSalted = true

shiroDbRealm = cn.wizzer.app.web.commons.shiro.realm.PlatformAuthorizingRealm
shiroDbRealm.credentialsMatcher = $sha256Matcher

fontshiroDbRealm = cn.wizzer.app.web.commons.shiro.realm.PlatformAuthorizingRealm
fontshiroDbRealm.credentialsMatcher = $sha256Matcher

DefautModularRealm=cn.wizzer.app.web.commons.shiro.realm.DefautModularRealm

securityManager.realms = $shiroDbRealm,$fontshiroDbRealm
securityManager.authenticator=$DefautModularRealm
authcStrategy = cn.wizzer.framework.shiro.pam.AnySuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
securityManager.cacheManager = $cacheManager
securityManager.rememberMeManager = $rememberMeManager

authc = cn.wizzer.app.web.commons.shiro.filter.PlatformAuthenticationFilter
authc.captchaParam=platformCaptcha
authc.loginUrl = /platform/login
logout.redirectUrl = /platform/login


fontauthc = cn.wizzer.app.web.commons.shiro.filter.FontAuthenticationFilter
authc.captchaParam=fontCaptcha
authc.loginUrl = /tracking/login
logout.redirectUrl = /tracking/login


[urls]
/platform/doLogin = anon
/assets/** = anon
/** = anon
/platform/** = authc
/tracking/doLogin = anon

结果悲剧了,没法进入系统了。。。

每个realm都会在构造方法中声明自己可接受的token类型哦

前后台都一样的。

不同的入口方法生成不同的token类的实例,就会对应realm呢

添加回复
请先登陆
回到顶部