NutzCN Logo
问答 如果使用authc = org.nutz.integration.shiro.SimpleAuthenticationFilter
发布于 2729天前 作者 binfoo 2515 次浏览 复制 上一个帖子 下一个帖子
标签:

是不是在进行权限控制时候,就不能使用
@RequiresPermissions("user:query")
而只能使用
@RequiresAuthentication?

16 回复

SimpleAuthenticationFilter跟@RequiresXXXXX 无相关性

我在用户登录时候使用的是SimpleAuthenticationFilter,但是无法进行权限操作
使用CaptchaFormAuthenticationFilter可以的。
相关代码

 @At
    @Filters // 覆盖UserModule类的@Filter设置,因为登陆可不能要求是个已经登陆的Session
    @POST
    public Object login(@Param("username") String username,
                        @Param("password") String password,
                        @Param("captcha") String captcha,
                        @Attr(scope = Scope.SESSION, value = "nutz_captcha") String _captcha) {
        NutMap re = new NutMap().setv("ok", false);
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated())
            return re.setv("ok", true);


        // session是否有效
        HttpSession session = Mvcs.getHttpSession(false);
        if (session == null) {
            return re.setv("msg", "session已过期");
        }
        if (!Toolkit.checkCaptcha(_captcha, captcha)) {
            return re.setv("msg", "验证码错误");
        }
        int userId = userService.fetch(username, password);
        if (userId < 0) {
            return re.setv("msg", "用户名或密码错误");
        }
        Toolkit.doLogin(new SimpleShiroToken(userId), userId);
        subject.getSession().setAttribute("me", userId);
        return re.setv("ok", true);
    }
 /**
     * 权限列表
     */
    @Ok("json")
    @RequiresPermissions("authority:permission:query")
    @At
    public Object permissions(@Param("query") String query, @Param("..") Pager pager) {
        return ajaxOk(query(Permission.class, Cnd.NEW().asc("id"), pager, null));
    }


    //---------------------------------------------
    // 用户操作

    /**
     * 更新用户所属角色/特许权限
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:sysuser:update")
    @At("/sysuser/update")
    @Aop(TransAop.READ_COMMITTED)
    public void updateUser(@Param("user") User user,
                           @Param("roles") List<Long> roles,
                           @Param("permissions") List<Long> permissions) {
        // 防御一下
        if (user == null)
            return;
        user = dao.fetch(User.class, user.getId());
        // 就在那么一瞬间,那个用户已经被其他用户删掉了呢
        if (user == null)
            return;
        if (roles != null) {
            List<Role> rs = new ArrayList<Role>(roles.size());
            for (long roleId : roles) {
                Role r = dao.fetch(Role.class, roleId);
                if (r != null) {
                    rs.add(r);
                }
            }
            dao.fetchLinks(user, "roles");
            if (user.getRoles().size() > 0) {
                dao.clearLinks(user, "roles");
            }
            user.setRoles(rs);
            dao.insertRelation(user, "roles");
        }
        if (permissions != null) {
            List<Permission> ps = new ArrayList<Permission>();
            for (long permissionId : permissions) {
                Permission p = dao.fetch(Permission.class, permissionId);
                if (p != null)
                    ps.add(p);
            }
            dao.fetchLinks(user, "permissions");
            if (user.getPermissions().size() > 0) {
                dao.clearLinks(user, "permissions");
            }
            user.setPermissions(ps);
            dao.insertRelation(user, "permissions");
        }
    }

登录admin之后访问
http://localhost:8080/page/simple_role.jsp
得到user.require.login

"我在用户登录时候使用的是SimpleAuthenticationFilter" 是啥意思???

就是shiro.ini配置,authc = org.nutz.integration.shiro.SimpleAuthenticationFilter

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

# realm声明
nutzdao_realm = com.binfoo.www.shiro.realm.SimpleAuthorizingRealm

# cookie, nutzcn使用超长时间的cookie,所以下面的timeout都很长
sessionIdCookie = org.apache.shiro.web.servlet.SimpleCookie
sessionIdCookie.name = sid
sessionIdCookie.maxAge = 946080000
sessionIdCookie.httpOnly = true
sessionManager.sessionIdCookie = $sessionIdCookie
sessionManager.sessionIdCookieEnabled = true
sessionManager.globalSessionTimeout = 946080000

authc = org.nutz.integration.shiro.SimpleAuthenticationFilter
authc.loginUrl = /sysuser/login
perms.loginUrl = /sysuser/login
roles.loginUrl = /sysuser/login
user.loginUrl = /sysuser/login
rest.loginUrl = /sysuser/login

[urls]
/rs/* = anon
/sysuser/logout = logout
/sysuser/error = anon
/sysuser/count = anon
/sysuser/profile/active/mail = anon
/sysuser/** = authc

admin用户有全部权限,然后呢,我登入权限配置的jsp提示需要登录

所以你根本没做登录?? POST /sysuser/login对应的入口方法没实现登录逻辑?

这个不就是实现登入了?

    Toolkit.doLogin(new SimpleShiroToken(userId), userId);
        subject.getSession().setAttribute("me", userId);
        return re.setv("ok", true);

debug一下, 看看执行doLogin没

执行了,登录是没有问题的

我把AuthorityModule 贴出来

package com.binfoo.www.module;


import com.binfoo.www.bean.Permission;
import com.binfoo.www.bean.Role;
import com.binfoo.www.bean.User;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.util.Daos;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.adaptor.JsonAdaptor;
import org.nutz.mvc.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 角色/权限管理. 基本假设: 一个用户属于多种角色,拥有多种特许权限. 每种角色拥有多种权限
 *
 * @author wendal
 */
@At("/admin/authority")
@IocBean
@Ok("void")//避免误写导致敏感信息泄露到服务器外
public class AuthorityModule extends BaseModule {

    //---------------------------------------------
    // 查询类

    /**
     * 用户列表
     */
    @RequiresPermissions("authority:sysuser:query")
    @At
    @Ok("json:{locked:'password|salt',ignoreNull:true}") //禁止把password和salt字段进行传输
    public Object users(@Param("query") String query, @Param("..") Pager pager) {
        return ajaxOk(query(User.class, Cnd.NEW().asc("id"), pager, null));
    }

    /**
     * 角色列表
     */
    @Ok("json")
    @RequiresPermissions("authority:role:query")
    @At
    public Object roles(@Param("query") String query, @Param("..") Pager pager) {
        return ajaxOk(query(Role.class, Cnd.NEW().asc("id"), pager, null));
    }

    /**
     * 权限列表
     */
    @Ok("json")
    @RequiresPermissions("authority:permission:query")
    @At
    public Object permissions(@Param("query") String query, @Param("..") Pager pager) {
        return ajaxOk(query(Permission.class, Cnd.NEW().asc("id"), pager, null));
    }


    //---------------------------------------------
    // 用户操作

    /**
     * 更新用户所属角色/特许权限
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:sysuser:update")
    @At("/sysuser/update")
    @Aop(TransAop.READ_COMMITTED)
    public void updateUser(@Param("user") User user,
                           @Param("roles") List<Long> roles,
                           @Param("permissions") List<Long> permissions) {
        // 防御一下
        if (user == null)
            return;
        user = dao.fetch(User.class, user.getId());
        // 就在那么一瞬间,那个用户已经被其他用户删掉了呢
        if (user == null)
            return;
        if (roles != null) {
            List<Role> rs = new ArrayList<Role>(roles.size());
            for (long roleId : roles) {
                Role r = dao.fetch(Role.class, roleId);
                if (r != null) {
                    rs.add(r);
                }
            }
            dao.fetchLinks(user, "roles");
            if (user.getRoles().size() > 0) {
                dao.clearLinks(user, "roles");
            }
            user.setRoles(rs);
            dao.insertRelation(user, "roles");
        }
        if (permissions != null) {
            List<Permission> ps = new ArrayList<Permission>();
            for (long permissionId : permissions) {
                Permission p = dao.fetch(Permission.class, permissionId);
                if (p != null)
                    ps.add(p);
            }
            dao.fetchLinks(user, "permissions");
            if (user.getPermissions().size() > 0) {
                dao.clearLinks(user, "permissions");
            }
            user.setPermissions(ps);
            dao.insertRelation(user, "permissions");
        }
    }

    /**
     * 用于显示用户-权限修改对话框的信息
     */
    @Ok("json")
    @RequiresPermissions("authority:sysuser:update")
    @At("/sysuser/fetch/permission")
    public Object fetchUserPermissions(@Param("id") long id) {
        User user = dao.fetch(User.class, id);
        if (user == null)
            return ajaxFail("not such user");
        user = dao.fetchLinks(user, "permissions");
        // TODO 优化为逐步加载
        List<Permission> permissions = dao.query(Permission.class, Cnd.orderBy().asc("name"));
        NutMap data = new NutMap();
        data.put("user", user);
        data.put("permissions", permissions);
        return ajaxOk(data);
    }

    /**
     * 用于显示用户-权限修改对话框的信息
     */
    @Ok("json")
    @RequiresPermissions("authority:sysuser:update")
    @At("/sysuser/fetch/role")
    public Object fetchUserRoles(@Param("id") long id) {
        User user = dao.fetch(User.class, id);
        if (user == null)
            return ajaxFail("not such user");
        user = dao.fetchLinks(user, "roles");
        // TODO 优化为逐步加载
        List<Role> roles = dao.query(Role.class, Cnd.orderBy().asc("name"));
        NutMap data = new NutMap();
        data.put("user", user);
        data.put("roles", roles);
        return ajaxOk(data);
    }

    //---------------------------------------------
    // Role操作

    /**
     * 新增一个角色
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:role:add")
    @At("/role/add")
    public void addRole(@Param("..") Role role) {
        if (role == null)
            return;
        dao.insert(role); // 注意,这里并没有用insertWith, 即总是插入一个无权限的角色
    }

    /**
     * 删除一个角色,其中admin角色禁止删除
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:role:delete")
    @At("/role/delete")
    public void delRole(@Param("..") Role role) {
        if (role == null)
            return;
        role = dao.fetch(Role.class, role.getId());
        if (role == null)
            return;
        // 不允许删除admin角色
        if ("admin".equals(role.getName()))
            return;
        dao.delete(Role.class, role.getId());
    }

    /**
     * 更新权限的一般信息或所拥有的权限
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:role:update")
    @At("/role/update")
    @Aop(TransAop.SERIALIZABLE) // 关键操作,强事务操作
    public void updateRole(@Param("role") Role role, @Param("permissions") List<Long> permissions) {
        if (role == null)
            return;
        if (dao.fetch(Role.class, role.getId()) == null)
            return;
        if (!Strings.isBlank(role.getAlias()) || !Strings.isBlank(role.getDescription())) {
            Daos.ext(dao, FieldFilter.create(Role.class, "alias|desc")).update(role);
        }
        if (permissions != null) {
            List<Permission> ps = new ArrayList<Permission>();
            for (Long permission : permissions) {
                Permission p = dao.fetch(Permission.class, permission);
                if (p != null)
                    ps.add(p);
            }
            // 如果有老的权限,先清空,然后插入新的记录
            // TODO 优化为直接清理中间表
            dao.fetchLinks(role, "permissions");
            if (role.getPermissions().size() > 0) {
                dao.clearLinks(role, "permissions");
            }
            role.setPermissions(ps);
            dao.insertRelation(role, "permissions");
        }
        // TODO 修改Role的updateTime
    }

    /**
     * 用于显示角色-权限修改对话框的信息
     */
    @Ok("json")
    @RequiresPermissions("authority:role:update")
    @At("/role/fetch")
    public Object fetchRolePermissions(@Param("id") long id) {
        Role role = dao.fetch(Role.class, id);
        if (role == null)
            return ajaxFail("not such role");
        role = dao.fetchLinks(role, null);
        // TODO 优化为逐步加载
        List<Permission> permissions = dao.query(Permission.class, Cnd.orderBy().asc("name"));
        NutMap data = new NutMap();
        data.put("role", role);
        data.put("permissions", permissions);
        return ajaxOk(data);
    }

    //--------------------------------------------------------------------
    // Permission操作

    /**
     * 新增一个权限
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:permission:add")
    @At("/permission/add")
    public void addPermission(@Param("..") Permission permission) {
        if (permission == null)
            return;
        dao.insert(permission);
    }

    /**
     * 删除一个角色
     *
     * @param permission
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:permission:delete")
    @At("/permission/delete")
    public void delPermission(@Param("..") Permission permission) {
        if (permission == null)
            return;
        // TODO 禁止删除authority相关的默认权限
        dao.delete(Permission.class, permission.getId());
    }

    /**
     * 修改权限的一般信息
     */
    @POST
    @AdaptBy(type = JsonAdaptor.class)
    @RequiresPermissions("authority:permission:update")
    @At("/permission/update")
    public void updateRole(@Param("..") Permission permission) {
        if (permission == null)
            return;
        if (dao.fetch(Permission.class, permission.getId()) == null)
            return;
        permission.setUpdateTime(new Date());
        permission.setCreateTime(null);
        Daos.ext(dao, FieldFilter.create(Permission.class, null, "name", true)).update(permission);
    }
}

写个这样的方法测试一下

    @At
    @Ok("raw")
    public void test() {
        Subject subject = SecurityUtils.getSubject();
        log.debug("isAuthenticated=" + subject.isAuthenticated());
        log.debug("isPermitted=" + subject.isPermitted("authority:permission:update"));
    }

好像是缓存空指针,是不是要在shiro中也要配置缓存

2017-05-11 17:14:28,969 org.nutz.mvc.impl.processor.FailProcessor.process(FailProcessor.java:28) WARN  - Error@/sysuser/test :
org.nutz.dao.DaoException: java.lang.NullPointerException
	at org.nutz.dao.impl.sql.run.NutDaoRunner._runWithoutTransaction(NutDaoRunner.java:128)
	at org.nutz.dao.impl.sql.run.NutDaoRunner._run(NutDaoRunner.java:81)
	at org.nutz.dao.impl.sql.run.NutDaoRunner.run(NutDaoRunner.java:70)
	at org.nutz.dao.impl.DaoSupport.run(DaoSupport.java:239)
	at org.nutz.dao.impl.DaoSupport._exec(DaoSupport.java:247)
	at org.nutz.dao.impl.NutDao$13.visit(NutDao.java:875)
	at org.nutz.dao.impl.entity.LinkFieldSet.visit(LinkFieldSet.java:41)
	at org.nutz.dao.impl.entity.NutEntity.visitOne(NutEntity.java:333)
	at org.nutz.dao.impl.NutDao$10.invoke(NutDao.java:612)
	at org.nutz.lang.Lang.each(Lang.java:1593)
	at org.nutz.dao.impl.NutDao.fetchLinks(NutDao.java:604)
	at org.nutz.dao.impl.NutDao.fetchLinks(NutDao.java:598)
	at com.binfoo.www.shiro.realm.SimpleAuthorizingRealm.doGetAuthorizationInfo(SimpleAuthorizingRealm.java:35)
	at org.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo(AuthorizingRealm.java:341)
	at org.apache.shiro.realm.AuthorizingRealm.isPermitted(AuthorizingRealm.java:462)
	at org.apache.shiro.realm.AuthorizingRealm.isPermitted(AuthorizingRealm.java:458)
	at org.apache.shiro.authz.ModularRealmAuthorizer.isPermitted(ModularRealmAuthorizer.java:223)
	at org.apache.shiro.mgt.AuthorizingSecurityManager.isPermitted(AuthorizingSecurityManager.java:113)
	at org.apache.shiro.subject.support.DelegatingSubject.isPermitted(DelegatingSubject.java:158)
	at com.binfoo.www.module.UserModule.test(UserModule.java:41)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:25)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.integration.shiro.NutShiroProcessor.process(NutShiroProcessor.java:126)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:22)
	at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
	at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
	at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
	at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:198)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
	at org.nutz.plugins.cache.dao.impl.provider.EhcacheDaoCacheProvider.getCache(EhcacheDaoCacheProvider.java:44)
	at org.nutz.plugins.cache.dao.impl.provider.EhcacheDaoCacheProvider.get(EhcacheDaoCacheProvider.java:21)
	at org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:159)
	at org.nutz.dao.DaoInterceptorChain.doChain(DaoInterceptorChain.java:66)
	at org.nutz.dao.impl.interceptor.DaoLogInterceptor.filter(DaoLogInterceptor.java:22)
	at org.nutz.dao.DaoInterceptorChain.doChain(DaoInterceptorChain.java:64)
	at org.nutz.dao.DaoInterceptorChain.invoke(DaoInterceptorChain.java:139)
	at org.nutz.dao.impl.sql.run.NutDaoRunner.runCallback(NutDaoRunner.java:147)
	at org.nutz.dao.impl.sql.run.NutDaoRunner._runWithoutTransaction(NutDaoRunner.java:114)
	... 77 more

你的shiro没有用ehcache? 仔细看ehcache.js里面的注释

可以了,我在shiro.ini加入这个

cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml

一切正常了?

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