文档章节

jfinal-shiro的shiro注解结合数据库url路径过滤,动态维护你的权限系统,支持ajax

Dreampie
 Dreampie
发布于 2014/09/12 11:12
字数 2726
阅读 1451
收藏 27

https://github.com/Dreampie/jfinal-shiro  的jfinal-shiro插件:

<dependency>
      <groupId>cn.dreampie</groupId>
      <artifactId>jfinal-shiro</artifactId>
      <version>${jfinal-shiro.version}</version>
 </dependency>

目前刚刚发布第一个版本0.1:

<jfinal-shiro.version>0.1</jfinal-shiro.version>

首先感谢jfinal-ext中原作者,该插件主要是针对ext插件的部分改进。

下面主要介绍两种使用方式:

    在web.xml里添加

    <!--权限过滤器 start-->
    <listener>
        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
    </listener>
    
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>
    <!--权限过滤器 end-->

    启用shiro   在jfinal config里configPlugin方法添加

 
 //shiro权限框架   在jfinal  plugins里添加shiro  plugin
        plugins.add(new ShiroPlugin(routes, new MyJdbcAuthzService()));

    添加shiro的过滤器  在jfinal config里configInterceptor方法添加

interceptors.add(new ShiroInterceptor());

public class User extends cn.dreampie.shiro.model.User<User> //user的model需要继承User
  1. 在方法上使用注解

    1. Shiro共有5个注解,分别如下:

      1. RequiresAuthentication:使用该注解标注的类,实例,方法在访问或调用时,当前Subject必须在当前session中已经过认证。

      2. RequiresGuest:使用该注解标注的类,实例,方法在访问或调用时,当前Subject可以是“gust”身份,不需要经过认证或者在原先的session中存在记录。

      3. RequiresPermissions:当前Subject需要拥有某些特定的权限时,才能执行被该注解标注的方法。如果当前Subject不具有这样的权限,则方法不会被执行。

      4. RequiresRoles:当前Subject必须拥有所有指定的角色时,才能访问被该注解标注的方法。如果当天Subject不同时拥有所有指定角色,则方法不会执行还会抛出AuthorizationException异常。

      5. RequiresUser:当前Subject必须是应用的用户,才能访问或调用被该注解标注的类,实例,方法。

    2. Shiro的认证注解处理是有内定的处理顺序的,如果有个多个注解的话,前面的通过了会继续检查后面的,若不通过则直接返回,处理顺序依次为(与实际声明顺序无关):
      RequiresRoles
      RequiresPermissions
      RequiresAuthentication
      RequiresUser
      RequiresGuest
      例如:你同时生命了RequiresRoles和RequiresPermissions,那就要求拥有此角色的同时还得拥有相应的权限。

    3. RequiresRoles可以用在Controller或者方法上。可以多个roles,默认逻辑为 AND也就是所有具备所有role才能访问。

            示例:

    //属于user角色
    @RequiresRoles("user")
     
    //必须同时属于user和admin角色
    @RequiresRoles({"user","admin"})
     
    //属于user或者admin之一。
    @RequiresRoles(value={"user","admin"},logical=Logical.OR)



  2. 其他使用方法类似。

  3. @RequiresPermissions
    @RequiresAuthentication
    @RequiresUser
    @RequiresGusst



  4. 详细可以参考玛雅牛的shiro注解使用,http://my.oschina.net/myaniu/blog/137205

  5. 基于数据库的权限设计与维护

    数据库的基本权限结构主要:用户->角色->权限

    表结构设计如下(h2数据库,使用其他数据修改部分sql语句之后使用):

    DROP TABLE IF EXISTS sec_user;
    DROP SEQUENCE IF EXISTS sec_user_id_seq;
    CREATE SEQUENCE sec_user_id_seq START WITH 1;
    CREATE TABLE sec_user (  --用户表
      id            BIGINT       NOT NULL DEFAULT NEXTVAL('sec_user_id_seq') PRIMARY KEY,
      username      VARCHAR(50)  NOT NULL COMMENT '登录名',
      providername  VARCHAR(50)  NOT NULL COMMENT '提供者',
      email         VARCHAR(200) COMMENT '邮箱',
      mobile        VARCHAR(50) COMMENT '手机',
      password      VARCHAR(200) NOT NULL COMMENT '密码',
      hasher   VARCHAR(200) NOT NULL COMMENT '加密类型',
      salt VARCHAR(200) NOT NULL COMMENT '加密盐',
      avatar_url    VARCHAR(255) COMMENT '头像',
      first_name    VARCHAR(10) COMMENT '名字',
      last_name     VARCHAR(10) COMMENT '姓氏',
      full_name     VARCHAR(20) COMMENT '全名',
      department_id BIGINT NOT NULL COMMENT '部门id',
      created_at    TIMESTAMP    NOT NULL,
      updated_at    TIMESTAMP,
      deleted_at    TIMESTAMP
    );
    
    DROP TABLE IF EXISTS sec_user_info;
    DROP SEQUENCE IF EXISTS sec_user_info_id_seq;
    CREATE SEQUENCE sec_user_info_id_seq START WITH 1;
    CREATE TABLE sec_user_info (-- 用户详细信息表
      id          BIGINT    NOT NULL DEFAULT NEXTVAL('sec_user_info_id_seq') PRIMARY KEY,
      user_id     BIGINT    NOT NULL COMMENT '用户id',
      creator_id  BIGINT COMMENT '创建者id',
      gender      INT DEFAULT 0 COMMENT '性别0男,1女',
      province_id BIGINT COMMENT '省id',
      city_id     BIGINT COMMENT '市id',
      county_id   BIGINT COMMENT '县id',
      street      VARCHAR(500) COMMENT '街道',
      zip_code    VARCHAR(50) COMMENT '邮编',
      created_at  TIMESTAMP NOT NULL,
      updated_at  TIMESTAMP,
      deleted_at  TIMESTAMP
    );
    
    DROP TABLE IF EXISTS sec_role;
    DROP SEQUENCE IF EXISTS sec_role_id_seq;
    CREATE SEQUENCE sec_role_id_seq START WITH 1;
    CREATE TABLE sec_role (--角色表
      id         BIGINT      NOT NULL DEFAULT NEXTVAL('sec_role_id_seq') PRIMARY KEY,
      name       VARCHAR(50) NOT NULL COMMENT '名称',
      value      VARCHAR(50) NOT NULL COMMENT '值',
      intro      VARCHAR(255) COMMENT '简介',
      pid        BIGINT DEFAULT 0 COMMENT '父级id',
      left_code  BIGINT DEFAULT 0 COMMENT '数据左边码',
      right_code BIGINT DEFAULT 0 COMMENT '数据右边码',
      created_at TIMESTAMP   NOT NULL,
      updated_at TIMESTAMP,
      deleted_at TIMESTAMP
    );
    
    DROP TABLE IF EXISTS sec_user_role;
    DROP SEQUENCE IF EXISTS sec_user_role_id_seq;
    CREATE SEQUENCE sec_user_role_id_seq START WITH 1;
    CREATE TABLE sec_user_role (--用户角色关系表
      id      BIGINT NOT NULL DEFAULT NEXTVAL('sec_user_role_id_seq') PRIMARY KEY,
      user_id BIGINT NOT NULL,
      role_id BIGINT NOT NULL
    );
    
    DROP TABLE IF EXISTS sec_permission;
    DROP SEQUENCE IF EXISTS sec_permission_id_seq;
    CREATE SEQUENCE sec_permission_id_seq START WITH 1;
    CREATE TABLE sec_permission (--权限表
      id         BIGINT      NOT NULL DEFAULT NEXTVAL('sec_permission_id_seq') PRIMARY KEY,
      name       VARCHAR(50) NOT NULL COMMENT '名称',
      value      VARCHAR(50) NOT NULL COMMENT '值',
      url        VARCHAR(255) COMMENT 'url地址',
      intro      VARCHAR(255) COMMENT '简介',
      pid        BIGINT DEFAULT 0 COMMENT '父级id',
      left_code  BIGINT DEFAULT 0 COMMENT '数据左边码',
      right_code BIGINT DEFAULT 0 COMMENT '数据右边码',
      created_at TIMESTAMP   NOT NULL,
      updated_at TIMESTAMP,
      deleted_at TIMESTAMP
    );
    
    
    DROP TABLE IF EXISTS sec_role_permission;
    DROP SEQUENCE IF EXISTS sec_role_permission_id_seq;
    CREATE SEQUENCE sec_role_permission_id_seq START WITH 1;
    CREATE TABLE sec_role_permission (--角色权限关系表
      id            BIGINT NOT NULL DEFAULT NEXTVAL('sec_role_permission_id_seq') PRIMARY KEY,
      role_id       BIGINT NOT NULL,
      permission_id BIGINT NOT NULL
    );

            数据结构基本完成,提示:pid,left_code,right_code是数据的树形结构设计和权限无关

            测试数据:

    --create role--
    
    INSERT INTO sec_role(id,name, value, intro, pid,left_code,right_code,created_at)
    VALUES (sec_role_id_seq.nextval,'超级管理员','R_ADMIN','',0,1,8, current_timestamp),
           (sec_role_id_seq.nextval,'系统管理员','R_MANAGER','',1,2,7,current_timestamp),
           (sec_role_id_seq.nextval,'会员','R_MEMBER','',2,3,4,current_timestamp),
           (sec_role_id_seq.nextval,'普通用户','R_USER','',2,5,6,current_timestamp);
    
    --create permission--
    INSERT INTO sec_permission(id, name, value, url, intro,pid,left_code,right_code, created_at)
    VALUES (sec_permission_id_seq.nextval,'管理员目录','P_D_ADMIN','/admin/**','',0,1,6,current_timestamp),
           (sec_permission_id_seq.nextval,'角色权限管理','P_ROLE','/admin/role/**','',1,2,3,current_timestamp),
           (sec_permission_id_seq.nextval,'用户管理','P_USER','/admin/user/**','',1,4,5,current_timestamp),
           (sec_permission_id_seq.nextval,'会员目录','P_D_MEMBER','/member/**','',0,9,10,current_timestamp),
           (sec_permission_id_seq.nextval,'普通用户目录','P_D_USER','/user/**','',0,11,12,current_timestamp);
    
    
    INSERT INTO sec_role_permission(id,role_id, permission_id)
    VALUES (sec_role_permission_id_seq.nextval,1,1),(sec_role_permission_id_seq.nextval,1,2),
           (sec_role_permission_id_seq.nextval,1,3),(sec_role_permission_id_seq.nextval,1,4),
           (sec_role_permission_id_seq.nextval,1,5),
    
           (sec_role_permission_id_seq.nextval,2,1),(sec_role_permission_id_seq.nextval,2,3),
           (sec_role_permission_id_seq.nextval,2,4),(sec_role_permission_id_seq.nextval,2,5),
    
           (sec_role_permission_id_seq.nextval,3,4),(sec_role_permission_id_seq.nextval,3,5),
    
           (sec_role_permission_id_seq.nextval,4,5);
      --user data--
    --create  admin--
    INSERT INTO sec_user(id, username, providername, email, mobile, password, hasher, salt, avatar_url, first_name, last_name, full_name,department_id, created_at)
    VALUES (sec_user_id_seq.nextval,'admin','dreampie','wangrenhui1990@gmail.com','18611434500','$shiro1$SHA-256$500000$ZMhNGAcL3HbpTbNXzxxT1Q==$wRi5AF6BK/1FsQdvISIY1lJ9Rm/aekBoChjunVsqkUU=','default_hasher','','','仁辉','王','仁辉&middot;王',1,current_timestamp),
           (sec_user_id_seq.nextval,'aaaaa','dreampie','aaaaa@gmail.com','18511400000','$shiro1$SHA-256$500000$ZMhNGAcL3HbpTbNXzxxT1Q==$wRi5AF6BK/1FsQdvISIY1lJ9Rm/aekBoChjunVsqkUU=','default_hasher','','','金彤','刘','金彤&middot;刘',2,current_timestamp);
    
    --create user_info--
    INSERT INTO sec_user_info(id, user_id, creator_id, gender,province_id,city_id,county_id,street,created_at)
    VALUES (sec_user_info_id_seq.nextval,1,0,0,1,2,3,'人民大学',current_timestamp),
           (sec_user_info_id_seq.nextval,2,0,0,1,2,3,'人民大学',current_timestamp);
    
    --create user_role--
    INSERT INTO sec_user_role(id, user_id, role_id)
    VALUES (sec_user_role_id_seq.nextval,1,1),
           (sec_user_role_id_seq.nextval,2,2);

            接下来实现两个关键接口,一个是shiro的JdbcRealm:        

    public class MyJdbcRealm extends AuthorizingRealm {
    
      /**
       * 登录认证
       *
       * @param token
       * @return
       * @throws org.apache.shiro.authc.AuthenticationException
       */
      protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        User user = null;
        String username = userToken.getUsername();
        if (ValidateKit.isEmail(username)) {
          user = User.dao.findFirstBy(" `user`.email =? AND `user`.deleted_at is null", username);
        } else if (ValidateKit.isMobile(username)) {
          user = User.dao.findFirstBy(" `user`.mobile =? AND `user`.deleted_at is null", username);
        } else {
          user = User.dao.findFirstBy(" `user`.username =? AND `user`.deleted_at is null", username);
        }
        if (user != null) {
          SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getStr("password"), getName());
          return info;
        } else {
          return null;
        }
      }
    
      /**
       * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
       *
       * @param principals
       * @return
       */
      protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String loginName = ((User) principals.fromRealm(getName()).iterator().next()).get("username");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> roleSet = new LinkedHashSet<String>(); // 角色集合
        Set<String> permissionSet = new LinkedHashSet<String>();  // 权限集合
        List<Role> roles = null;
        User user = User.dao.findFirstBy(" `user`.username =? AND `user`.deleted_at is null", loginName);
        if (user != null) {
          //遍历角色
          roles = Role.dao.findUserBy("", user.getLong("id"));
        } else {
          SubjectKit.getSubject().logout();
        }
    
        loadRole(roleSet, permissionSet, roles);
        info.setRoles(roleSet); // 设置角色
        info.setStringPermissions(permissionSet); // 设置权限
        return info;
      }
    
      /**
       * @param roleSet
       * @param permissionSet
       * @param roles
       */
      private void loadRole(Set<String> roleSet, Set<String> permissionSet, List<Role> roles) {
        List<Permission> permissions;
        for (Role role : roles) {
          //角色可用
          if (role.getDate("deleted_at") == null) {
            roleSet.add(role.getStr("value"));
            permissions = Permission.dao.findByRole("", role.getLong("id"));
            loadAuth(permissionSet, permissions);
          }
        }
      }
    
      /**
       * @param permissionSet
       * @param permissions
       */
      private void loadAuth(Set<String> permissionSet, List<Permission> permissions) {
        //遍历权限
        for (Permission permission : permissions) {
          //权限可用
          if (permission.getDate("deleted_at") == null) {
            permissionSet.add(permission.getStr("value"));
          }
        }
      }
    
      /**
       * 更新用户授权信息缓存.
       */
    
      public void clearCachedAuthorizationInfo(Object principal) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
        clearCachedAuthorizationInfo(principals);
      }
    
      /**
       * 清除所有用户授权信息缓存.
       */
      public void clearAllCachedAuthorizationInfo() {
        Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
        if (cache != null) {
          for (Object key : cache.keys()) {
            cache.remove(key);
          }
        }
      }
    }

         实现数据库权限的初始化加载:

    public class MyJdbcAuthzService implements JdbcAuthzService {
      @Override
      public Map<String, AuthzHandler> getJdbcAuthz() {
        //加载数据库的url配置
        Map<String, AuthzHandler> authzJdbcMaps = new HashMap<String, AuthzHandler>();
        //遍历角色
        List<Role> roles = Role.dao.findAll();
        List<Permission> permissions = null;
        for (Role role : roles) {
          //角色可用
          if (role.getDate("daleted_at") == null) {
            permissions = Permission.dao.findByRole("", role.get("id"));
            //遍历权限
            for (Permission permission : permissions) {
              //权限可用
              if (permission.getDate("daleted_at") == null) {
                if (permission.getStr("url") != null && !permission.getStr("url").isEmpty()) {
                  authzJdbcMaps.put(permission.getStr("url"), new JdbcPermissionAuthzHandler(permission.getStr("value")));
                }
              }
            }
          }
        }
        return authzJdbcMaps;
      }
    }

前台使用验证码时传入username,password,captcha  三个参数,第三个是验证码参数名,提前把验证码内容存入session,shiro会自动进行验证,注意名称为captcha

主要结构是权限表里的url-value,如果需要访问

url:  /admin/**   需要value:P_D_ADMIN

把这些权限绑定到角色之后,角色绑定给用户就相当于,用户下面有很多这些  url-value

    1.系统启动的时候把这个对应关系加载到内存或者缓存  //cn.dreampie.shiro.core.ShiroKit

    2. 用户登录的时候把用户对应的角色所有的权限加载到缓存,这一步是shiro自己实现

    3.当用户访问某个url的时候 如访问/admin/index,过滤器会匹配到/admin/**,这个url需要拥有P_D_ADMIN的权限

    4.然后使用shiro的接口hasPremission(value),判断用户是否拥有这个权限//cn.dreampie.shiro.core.ShiroInterceptor

    5.放行或者拒绝访问返回403状态

jfinal-shiro支持Ajax登陆/退出,使用json数据

shiro.ini  配置文件:

[users]
guest = guest,guest

[main]
authc = cn.dreampie.shiro.ShiroFormAuthenticationFilter
#登陆请求路径
authc.loginUrl = /signin
#分角色登录配置
#authc.loginUrlMap = user:/login,admin:/admin/login
#登陆成功跳转路径
authc.successUrl = /
#登陆失败跳转路径
authc.failureUrl = /signin
#登陆成功跳转路径
#authc.failureUrlMap = user:/login.ftl,admin:/admin/login.ftl

signout = cn.dreampie.shiro.ShiroLogoutFilter
#退出跳转路径
signout.redirectUrl = /
#分角色退出跳转
#logout.redirectUrlMap = user:/index,admin:/index
#realm  上面实现的获取登陆用户和用户权限的借口类
jdbcRealm = org.icedog.common.shiro.MyJdbcRealm
securityManager.realm = $jdbcRealm

passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordMatcher = cn.dreampie.shiro.ShiroPasswordMatcher
passwordMatcher.passwordService = $passwordService
jdbcRealm.credentialsMatcher = $passwordMatcher

#cache
shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
shiroCacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $shiroCacheManager

#session
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionDAO.activeSessionsCacheName = shiro-activeSessionCache
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager
sessionListener = cn.dreampie.shiro.listeners.ShiroSessionListener
securityManager.sessionManager.sessionListeners = $sessionListener

# cookie for single sign on
#cookie = org.apache.shiro.web.servlet.SimpleCookie
#cookie.name = www.dreampie.cn.session
#cookie.path = /
#cookie.maxAge = -1
#sessionManager.sessionIdCookie = $cookie
# 1,800,000 milliseconds = 30 mins
securityManager.sessionManager.globalSessionTimeout = 1200000
;sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
;sessionValidationScheduler.interval = 1200000
;securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler
securityManager.sessionManager.sessionValidationSchedulerEnabled = false
securityManager.sessionManager.deleteInvalidSessions = false
;securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled = false

[urls]
/signin = authc
/signout = signout
/** = anon



如果你使用freemarker作为模板,推荐使用jfinal-shiro-freemarker标签库 http://my.oschina.net/wangrenhui1990/blog/312741

https://github.com/Dreampie?tab=repositories 目录下有多款插件:

cn.dreampie.jfinal-shiro     https://github.com/Dreampie/jfinal-shiro    shiro插件

cn.dreampie.jfinal-shiro-freemarker   https://github.com/Dreampie/jfinal-shiro-freemarker    shiro插件实现的freemarker标签库

cn.dreampie.jfinal-web     https://github.com/Dreampie/jfinal-web   相关web插件,简洁model实现

cn.dreampie.jfinal-utils        https://github.com/Dreampie/jfinal-utils   部分jfinal工具

cn.dreampie.jfinal-tablebind        https://github.com/Dreampie/jfinal-tablebind   jfinal的table自动绑定插件,支持多数据源

cn.dreampie.jfinal-flyway      https://github.com/Dreampie/jfinal-flyway   数据库脚本升级插件,开发中升级应用时,使用脚本同步升级数据库或者回滚

cn.dreampie.jfinal-captcha      https://github.com/Dreampie/jfinal-captcha   基于jfinal render的超简单验证吗插件

cn.dreampie.jfinal-quartz       https://github.com/Dreampie/jfinal-quartz   基于jfinal 的quartz管理器

cn.dreampie.jfinal-sqlinxml      https://github.com/Dreampie/jfinal-sqlinxml   基于jfinal 的类似ibatis的sql语句管理方案

cn.dreampie.jfinal-lesscss       https://github.com/Dreampie/jfinal-lesscss   java实现的lesscsss实时编译插件,可以由于jfinal

cn.dreampie.jfinal-coffeescript     https://github.com/Dreampie/jfinal-coffeescript   java实现的coffeescript实时编译插件,可以由于jfinal 

cn.dreampie.jfinal-akka    https://github.com/Dreampie/jfinal-akka   java使用akka执行异步任务

cn.dreampie.jfinal-mailer       https://github.com/Dreampie/jfinal-mailer   使用akka发布邮件的jfinal插件

cn.dreampie.jfinal-slf4j     https://github.com/Dreampie/jfinal-slf4j   让jfinal使用slf4j的日志api

部分内容借鉴了网络资料

© 著作权归作者所有

Dreampie
粉丝 292
博文 23
码字总数 16536
作品 6
朝阳
其他
私信 提问
加载中

评论(7)

Dreampie
Dreampie 博主

引用来自“王仁辉(java)”的评论

引用来自“delicate”的评论

博主 有没有独立的jfinal+shiro的demo啊

点击此处输入评论

暂时没有,你可以把前端换成freemarker,完全不影响使用,现在有些同学已经在用了,你也可以试试
delicate
delicate
博主 有没有独立的jfinal+shiro的demo啊
Dreampie
Dreampie 博主

引用来自“liuxuehua12”的评论

securityManager.sessionManager.globalSessionTimeout = 1200000
;sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
;sessionValidationScheduler.interval = 1200000
;securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler
securityManager.sessionManager.sessionValidationSchedulerEnabled = false
securityManager.sessionManager.deleteInvalidSessions = false
;securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled = false

[urls]
/login = anon
/checklogin = anon
/logout = signout
/** = authc
/login 如果是你的登陆url 配置为 /login=authc #authc 指的是上面配置的filter ShiroFormAuthenticationFilter /logout 退出登陆url 配置为 /logout = signout # signout 指的是上面配置的filter ShiroLogoutFilter 您的配置 应该是 /login = authc /logout = signout /** = anon /checklogin 不用配 它被 /**=anon包含了 anon表示不会经过登录和退出相关的filter,除了登陆和退出的权限 其他权限都存在数据库里 如果还有问题 qq:173956022 联系我
l
liuxuehua12
我在ShiroInterceptor中添加对上面几个的过滤就没问题了
private String[] noans = {"/login","/login/","/checklogin"};
@Override
public void intercept(ActionInvocation ai) {
   String actionKey = ai.getActionKey();
//路径权限 //注解权限
   //过滤不需要权限控制的
   boolean need = true;
   for(String p : noans){
     if(p.equalsIgnoreCase(actionKey)){
       need = false;
       break;
     }
   }
  if(need){
   List<AuthzHandler> ahs = ShiroKit.getAuthzHandler(ai.getController().getRequest(), actionKey);
   //权限验证
   if (assertNoAuthorized(ai, ahs)) return;
  }
// 执行正常逻辑
ai.invoke();
}
l
liuxuehua12
securityManager.sessionManager.globalSessionTimeout = 1200000
;sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
;sessionValidationScheduler.interval = 1200000
;securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler
securityManager.sessionManager.sessionValidationSchedulerEnabled = false
securityManager.sessionManager.deleteInvalidSessions = false
;securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled = false

[urls]
/login = anon
/checklogin = anon
/logout = signout
/** = authc
l
liuxuehua12
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordMatcher = cn.dreampie.shiro.ShiroPasswordMatcher
passwordMatcher.passwordService = $passwordService
jdbcRealm.credentialsMatcher = $passwordMatcher

#cache
shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
shiroCacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $shiroCacheManager

#session
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionDAO.activeSessionsCacheName = shiro-activeSessionCache
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager
sessionListener = cn.dreampie.shiro.listeners.ShiroSessionListener
securityManager.sessionManager.sessionListeners = $sessionListener

l
liuxuehua12
你好,我用了你的这个权限插件,发现授权不对,/login页面都拦截了
我参考了你示例的shiro.ini配置,麻烦看下对不?
[users]
guest = guest,guest

[main]
authc = cn.dreampie.shiro.ShiroFormAuthenticationFilter //这里为什么用自己的?不明白
authc.loginUrl = /login

authc.successUrl = /
authc.failureUrl = /login

signout = cn.dreampie.shiro.ShiroLogoutFilter //这里为什么用自己的?不明白
signout.redirectUrl = /login

#anon = cn.dreampie.shiro.ShiroAnonymousFilter

#realm
jdbcRealm = com.sxtaxi.common.shiro.MyJdbcRealm
securityManager.realm = $jdbcRealm


JFinal的Shiro权限管理插件 2.0 版发布,支持JFinal 2.0

JFinal的Shiro权限管理插件 更新说明: 1)支持JFinal2.0 2)添加了一些实际项目中的代码供参考。 3)由于shiro需要与具体的业务整合才能使用,所以这个插件仅仅是方便在jfinal中使用shiro。...

玛雅牛
2015/08/18
6.1K
24
JFinal Authority 1.1 分布 jfinal 权限后台

更新内容 20140505 使用redis缓存 重写shiro sessionDao实现分布式session 20140504 添加redis缓存 20140504 过滤简单的 xss攻击 20140429 修复bug 登录过时 ajax请求没有跳转到登录页面 20...

12叔
2014/05/09
6.2K
27
给JFinal添加Shiro插件功能,支持Shiro所有注解-实现篇

2015年8月3日更新: 支持JFinal 2.0 版本,同时给出了一些实际代码,想见git @JFinal给出了一些好的建议,已重构部分代码。 代码放在oschina的git上,访问地址: http://git.oschina.net/mya...

玛雅牛
2013/06/12
16.2K
8
jfinal整合shiro回顾

目前jfinal使用shiro进行身份验证和授权的后台实现已完成,现在我再来总结下学习过程及代码实现过程。最近半年多项目开发都用.net,但又不甘心用了一年多的java,jfinal就这样被废弃,所以就...

一个yuanbeth
2017/08/30
1K
4
给JFinal添加Shiro插件功能,支持Shiro所有注解

个人实现了给JFinal添加Shiro插件功能,支持Shiro所有注解。 写了三篇博客来介绍,还请@JFinal指点。 给JFinal添加Shiro插件功能,支持Shiro所有注解-实现篇 给JFinal添加Shiro插件功能,支持...

玛雅牛
2013/06/13
6.2K
9

没有更多内容

加载失败,请刷新页面

加载更多

64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
今天
13
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
今天
7
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
今天
10
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
今天
12
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部