精华内容
下载资源
问答
  • Shiro是一个强大且易用的Java平台的开源权限框架,用于身份验证、授权、加解密和会话管理,它使用简单,可以快速、轻松地让任何应用程序获得如下需求的支持: (1)用户,角色,权限,资源; (2)用户分配角色,...
  • 动态权限框架源码

    2018-12-08 12:36:40
    几百万日活的app正在使用的动态权限框架,使用简单,耦合性低
  • WPF权限框架

    2019-01-24 19:50:11
    WPF权限框架账户密码都已经默认 目前服务端和客户端放在一个解决方案下, 如果后期的自行修改的源工程, 建议服务端客户端分离。
  • shiro权限框架,数据库mysql,框架用的是springmvc+mybatis+maven部署直接可用
  • 领域驱动设计-netcore2.0-角色权限框架
  • 基于MySQL的通用权限框架(完整源码),【权限系统】基于MySQL的通用权限框架(完整源码)
  • Apache Shiro 是 Java 的一个安全框架。我们经常看到它被拿来和 Spring 的 Security 来对比。大部分人认为 Shiro 比 Security 要简单
  • 学习权限框架

    2019-03-16 10:00:55
    用到的是oracle数据库,ssm框架,权限的分配和新增权限包含角色管理
  • spring权限框架教程

    2018-06-29 15:26:00
    spring security权限框架简要介绍, 可结合文档和官网编写个小Demo
  • ssm 权限框架源码

    2017-06-14 16:23:03
    java spring springmvc mybatis shiro 权限后台框架完整
  • C# MVC权限框架 包含工作流程 用户管理 菜单管理 部门管理 权限管理 前端采用layui 数据库房屋采用EF,
  • 集成shiro权限框架

    2014-02-07 10:34:24
    在项目中集成shiro权限框架 Shiro是一个功能强大的轻量级权限框架,相对其它权限框架(比如spring security)来说,要易用得很,下面,我给大家讲讲如何在一个项目中简单整合shiro。 我们通常所说的权限,就是要...
  • SpringBoot权限框架

    千次阅读 2020-05-12 00:16:42
    简单快速的在项目中进行权限验证 一、导入依赖 <dependency> <groupId>cn.gjing</groupId> <artifactId>tools-auth</artifactId> <version>1.0.0</version> </...

    简单快速的在项目中进行权限验证

    一、导入依赖

    <dependency>
        <groupId>cn.gjing</groupId>
        <artifactId>tools-auth</artifactId>
        <version>1.0.1</version>
    </dependency>
    

    二、权限注解

    该注解使用在API上,用于对用户请求方法时进行身份认证

    1、@RequiredPermissions

    权限认证,请求的用户需要存在该注解中设置的权限,否则抛出PermissionAuthorizationException

    参数描述
    value需要的权限

    2、@RequiredRoles

    角色认证,请求的用户需要存在该注解中设置的角色,否则抛出RoleAuthorizationException

    参数描述
    value需要的角色

    三、token生成器

    主要用来生成Token和解析Token,使用时可以通过@Resource注解进行依赖注入

    public class TestController {
        @Resource
        private TokenAssistant tokenAssistant;
        
        @GetMapping("/token")
        public void getToken() {
            Map<String, Object> map = new HashMap<>(16);
            map.put("user", "张三");
            String token = this.tokenAssistant.createToken(map);
            System.out.println("生成的token:" + map);
            System.out.println("解析token:" + this.tokenAssistant.parseToken(token));
        }
    }
    

    四、启动类增加注解

    在项目启动类增加@EnableAuthorization注解用于开启项目权限校验

    五、设置权限认证监听器

    通过监听器可以对用户拥有的权限进行提供以及进行自己的认证校验

    /**
     * @author Gjing
     **/
    @Component
    public class MyListener implements AuthorizationListener {
        /**
         * 增加用户的访问权限用于对增加了权限注解的方法进行身份认证,如果返回null会抛出NoAccountException
         * 这里模拟权限数据,给当前请求的用户增加admin角色和add权限。实际使用时
         * 用户权限你可以保存在任何地方
         *
         * @param token 用户Token
         * @return AuthorizationMetaData
         */
        @Override
        public AuthorizationMetaData supplyAccess(String token) {
            SimpleAuthorizationMetaData metaData = new SimpleAuthorizationMetaData();
            metaData.addRole("admin");
            metaData.addPermission("add");
            return metaData;
        }
    
        /**
         * 权限注解验证通过后会触发该方法,你可以在这里做一些项目中自己的权限认证逻辑
         *
         * @param token 用户Token
         */
        @Override
        public void authentication(String token) {
    
        }
    
        /**
         * 验证全部通过后且方法执行完毕
         *
         * @param request HttpServletRequest
         * @param method  请求的方法
         */
        @Override
        public void authenticationSuccess(HttpServletRequest request, Method method) {
            System.out.println();
        }
    }
    

    六、额外配置

    可以通过这些配置控制拦截路径和过滤路径,以及token存在的请求头名称等等…全部配置如下:

    tools:
      auth:
        # 拦截的路径
        path: /**
        # 排除的路径
        filter: 
        # 生成token的加密方式
        type: hs256
        # token存放的请求头名称
        header: Authorization
        # 加密的盐
        salt: 
    

    展开全文
  • shiro权限框架资料.zip

    2021-06-21 11:55:41
    shiro 权限框架学习资料, 从最基本的maven 工程到springboot 的整合, 再到一个通用的RBAC 权限框架模板的设计与创作, 包括视频, 源码, 资料, 稳定, 笔记, 软件, 依赖等等
  • Java SSM+Shiro权限框架

    2017-09-25 16:32:04
    Java SSM+Shiro权限框架
  • 这是兼容6.0权限处理的一套框架,具体效果及实现请看这里:http://blog.csdn.net/z240336124/article/details/53174400
  • 3. 掌握基于url的权限管理(不使用Shiro权限框架的情况下实现权限管理) 4. shiro实现用户认证 5. shiro实现用户授权 6. shiro与企业web项目整合开发的方法 权限管理原理知识 什么是权限管理 只要有用户参与的系统一般...

    知识清单

    1.了解基于资源的权限管理方式
    2. 掌握权限数据模型
    3. 掌握基于url的权限管理(不使用Shiro权限框架的情况下实现权限管理)
    4. shiro实现用户认证
    5. shiro实现用户授权
    6. shiro与企业web项目整合开发的方法

    权限管理原理知识

    什么是权限管理

    只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制。按照安全规则或安全策略控制用户可以访问而且只能访问自己被授权的资源。
    权限管理包括用户认证和用户授权两部分。

    用户认证

    用户认证概念

    用户认证—— 用户去访问系统,系统需要验证用户身份的合法性。最常用的用户身份认证方法:1.用户密码方式、2.指纹打卡机、3.基于证书的验证方法。系统验证用户身份合法,用户方可访问系统的资源。

    用户认证流程


    关键对象

    subject:主体,理解为用户,可能是程序,都要去访问系统的资源,系统需要对subject进行身份认证。
    principal:身份信息,通常是唯一的,一个主体可以有多个身份信息,但是只能有一个主身份信息(primary  principal)。
    credential:凭证信息,可以是密码、证书、指纹等。
    总结:主体在进行身份认证时需要提供身份信息和凭证信息。

    用户授权

    用户授权概念

    用户授权,简单理解为访问控制,在用户认证通过后,系统对用户访问资源进行控制,当用户具有资源的访问权限方可访问。

    授权流程


    其中橙色为授权流程

    关键对象

    授权的过程可以理解为  who  对 what(which) 进行how操作
    who:主体,即subject,subject在认证通过后,系统进行访问控制。
    what(which):资源(Resource) ,subject必须具备资源访问权限才可以访问该资源。资源包括很多方面比如:用户列表页面、商品修改菜单、商品id为001的商品信息。
    资源分为资源类型和资源实例
    例如系统的用户信息就是资源类型,相当于Java类。
    系统中id为001的用户就是资源实例,相当于new的Java对象。
    how:权限/许可(permission),针对资源的权限或许可,subject必须具有permission方可访问资源,如何访问/操作需要定义permission,权限比如:用户添加、用户添加、商品删除。

    权限模型

    主体(账号、密码)
    资源(资源名称,访问地址)
    权限(权限名称、资源id)
    角色(角色名称)
    角色和权限关系(角色id、权限id)
    如下图:

    通常企业开发中将资源和权限合并为一张权限表,如下:
    资源(资源名称、访问地址)
    权限(权限名称、资源id)
    合并为:
    权限(权限名称、资源名称、资源访问地址)

    上图被称为权限管理的通用模型,不过在企业开发中根据系统自身特点还会对上图进行修改,但是用户、角色、权限、用户角色关系、角色权限关系是必不可少的。

    分配权限

    用户需要分配相应的权限才可以访问相应的资源。权限是对资源的操作许可。
    通常给用户分配资源权限需要将权限信息持久化,比如存储在关系数据库中。
    把用户信息、权限管理、用户分配的权限信息写入到数据库(权限数据模型)。

    权限控制(授权核心)

    基于角色的访问控制

    RBAC (Role  based access  control) 基于角色的访问控制
    比如:
    系统角色包括:部门经理、总经理...(角色针对用户进行划分)
    系统中代码实现:
    //如果该user是部门经理则可以访问if中的代码
    if(user.getRole("部门经理")){
        // 系统资源内容
        // 用户报表查看
    }
    问题:
    角色是针对人进行划分的,人作为用户在系统中属于活动内容,如果该角色可以访问的资源出现变更,则需要修改代码,比如:需要变更为部门经理和总经理都可以进行用户报表查看,代码改为:
    if(user.getRole("部门经理") || user.getRole("总经理")){
        // 系统资源内容
        // 用户报表查看
    }
    由此可以发现基于角色的访问控制是不利于系统维护的(可扩展性不强)

    基于资源的访问控制

    RBAC (Resource  based  access control)  基于资源的访问控制
    资源在系统中是不变的,比如资源有:类中的方法,页面中的按钮
    对资源的访问需要具有permission权限,代码可以写为:
    if(user.hasPermission("用户报表查看(权限标识符)")){
        // 系统资源内容
        // 用户报表查看
    }
    上面的方法就可以解决用户角色变更而不用修改上边权限控制的代码。
    如果需要变更权限只需要在分配权限模块去操作,给部门经理或总经理增加或解除权限
    建议使用基于资源的访问控制实现权限管理。

    权限管理解决方案

    什么是粗粒度权限和细粒度权限?

    粗粒度权限管理,是对资源类型的管理,资源类型比如:菜单、url连接、用户添加页面、用户信息、类方法、页面中按钮。
    粗粒度权限管理比如:超级管理员可以访问用户添加页面、用户信息等全部页面。
    部门管理员可以访问用户信息页面,包括页面中所有按钮。

    细粒度的权限管理,对资源实例的权限管理。资源实例就是资源类型的具体化,比如:用户id为001的修改连接,1110班的用户信息、行政部的员工。
    细粒度的权限管理就是数据级别的权限管理。
    细粒度权限管理比如:部门经理只可以访问本部门的员工信息,用户只可以看到自己的菜单,大区经理只能查看本辖区的销售订单...

    粗粒度和细粒度例子:
    系统中有一个用户查询页面,对用户列表查询分权限,如粗粒度管理,张三和李四都有用户列表查询的权限,张三和李四都可以访问用户列表查询。
    进一步进行细粒度的管理,张三(行政部)和李四(开发部)只可以查询自己本部门的用户信息,张三只能查看行政部的用户信息,李四只能查询开发部门的用户信息。细粒度的权限管理就是数据级别的权限管理。

    如何实现粗粒度和细粒度的权限管理

    如何实现粗粒度的权限管理?
    粗粒度权限管理比较容易将权限管理代码抽取出来在系统架构级别统一管理。比如:通过SpringMVC的拦截器实现授权。
    如何实现细粒度的权限管理?
    对细粒度的权限管理在数据级别是没有共性可言的,针对细粒度的权限管理就是系统业务逻辑的一部分,如果在业务层去处理相对简单,如果将细粒度的权限管理统一在系统架构级别去抽取,比较困难,即使进行了抽取,功能也可能存在扩展性不全的弊端。建议细粒度权限管理放在业务层去控制。比如:部门经理只查询本部门员工信息,在Service接口提供一个部门id的参数,controller中根据当前用户信息得到该用户属于哪个部门,调用service时将部门id传入service,实现该用户只查询本部门的员工。

    基于url拦截的方式实现

    基于url拦截的方式实现在实际开发中是比较常用的一种方式。
    对于web系统,通过filter过滤器实现url拦截,也可以通过SpringMVC的拦截器实现基于URL的拦截。

    使用权限管理框架来实现

    对于粗粒度的权限管理,建议使用优秀的权限管理框架进行实现,节省开发成本,提高开发效率。
    Shiro就是一个优秀的权限管理框架。

    基于URL的权限管理

    基于url的权限管理流程



    搭建环境

    数据库

    MySQL数据库中创建表:用户表、角色表、权限表(实质是权限和资源的结合)、用户角色关系表、角色权限关系表

    新建数据库shiro, 为了节约测试时间,在SpringMVC+mybatis基础之上进行整合(导入以前的基本数据),并导入权限数据如下:

    有关权限的SQL脚本如下:
    shiro_sql_table.sql
    /*
    SQLyog v10.2 
    MySQL - 5.1.72-community : Database - shiro
    *********************************************************************
    */
    
    
    /*!40101 SET NAMES utf8 */;
    
    /*!40101 SET SQL_MODE=''*/;
    
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    /*Table structure for table `sys_permission` */
    
    CREATE TABLE `sys_permission` (
      `id` bigint(20) NOT NULL COMMENT '主键',
      `name` varchar(128) NOT NULL COMMENT '资源名称',
      `type` varchar(32) NOT NULL COMMENT '资源类型:menu,button,',
      `url` varchar(128) DEFAULT NULL COMMENT '访问url地址',
      `percode` varchar(128) DEFAULT NULL COMMENT '权限代码字符串',
      `parentid` bigint(20) DEFAULT NULL COMMENT '父结点id',
      `parentids` varchar(128) DEFAULT NULL COMMENT '父结点id列表串',
      `sortstring` varchar(128) DEFAULT NULL COMMENT '排序号',
      `available` char(1) DEFAULT NULL COMMENT '是否可用,1:可用,0不可用',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    /*Table structure for table `sys_role` */
    
    CREATE TABLE `sys_role` (
      `id` varchar(36) NOT NULL,
      `name` varchar(128) NOT NULL,
      `available` char(1) DEFAULT NULL COMMENT '是否可用,1:可用,0不可用',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    /*Table structure for table `sys_role_permission` */
    
    CREATE TABLE `sys_role_permission` (
      `id` varchar(36) NOT NULL,
      `sys_role_id` varchar(32) NOT NULL COMMENT '角色id',
      `sys_permission_id` varchar(32) NOT NULL COMMENT '权限id',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    /*Table structure for table `sys_user` */
    
    CREATE TABLE `sys_user` (
      `id` varchar(36) NOT NULL COMMENT '主键',
      `usercode` varchar(32) NOT NULL COMMENT '账号',
      `username` varchar(64) NOT NULL COMMENT '姓名',
      `password` varchar(32) NOT NULL COMMENT '密码',
      `salt` varchar(64) DEFAULT NULL COMMENT '盐',
      `locked` char(1) DEFAULT NULL COMMENT '账号是否锁定,1:锁定,0未锁定',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    /*Table structure for table `sys_user_role` */
    
    CREATE TABLE `sys_user_role` (
      `id` varchar(36) NOT NULL,
      `sys_user_id` varchar(32) NOT NULL,
      `sys_role_id` varchar(32) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
    
    shiro_sql_table_data.sql
    /*
    SQLyog v10.2 
    MySQL - 5.1.72-community : Database - shiro
    *********************************************************************
    */
    
    
    /*!40101 SET NAMES utf8 */;
    
    /*!40101 SET SQL_MODE=''*/;
    
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    /*Data for the table `sys_permission` */
    
    insert  into `sys_permission`(`id`,`name`,`type`,`url`,`percode`,`parentid`,`parentids`,`sortstring`,`available`) values 
    (1,'权限','','',NULL,0,'0/','0','1'),(11,'商品管理','menu','/item/queryItem.action',NULL,1,'0/1/','1.','1'),
    (12,'商品新增','permission','/item/add.action','item:create',11,'0/1/11/','','1'),
    (13,'商品修改','permission','/item/editItem.action','item:update',11,'0/1/11/','','1'),
    (14,'商品删除','permission','','item:delete',11,'0/1/11/','','1'),
    (15,'商品查询','permission','/item/queryItem.action','item:query',11,'0/1/15/',NULL,'1'),
    (21,'用户管理','menu','/user/query.action','user:query',1,'0/1/','2.','1'),
    (22,'用户新增','permission','','user:create',21,'0/1/21/','','1'),
    (23,'用户修改','permission','','user:update',21,'0/1/21/','','1'),
    (24,'用户删除','permission','','user:delete',21,'0/1/21/','','1');
    
    /*Data for the table `sys_role` */
    
    insert  into `sys_role`(`id`,`name`,`available`) values 
    	('ebc8a441-c6f9-11e4-b137-0adc305c3f28','商品管理员','1'),
    	('ebc9d647-c6f9-11e4-b137-0adc305c3f28','用户管理员','1');
    
    /*Data for the table `sys_role_permission` */
    
    insert  into `sys_role_permission`(`id`,`sys_role_id`,`sys_permission_id`) values 
    	('ebc8a441-c6f9-11e4-b137-0adc305c3f21','ebc8a441-c6f9-11e4-b137-0adc305c','12'),
    	('ebc8a441-c6f9-11e4-b137-0adc305c3f22','ebc8a441-c6f9-11e4-b137-0adc305c','11'),
    	('ebc8a441-c6f9-11e4-b137-0adc305c3f24','ebc9d647-c6f9-11e4-b137-0adc305c','21'),
    	('ebc8a441-c6f9-11e4-b137-0adc305c3f25','ebc8a441-c6f9-11e4-b137-0adc305c','15'),
    	('ebc9d647-c6f9-11e4-b137-0adc305c3f23','ebc9d647-c6f9-11e4-b137-0adc305c','22'),
    	('ebc9d647-c6f9-11e4-b137-0adc305c3f26','ebc8a441-c6f9-11e4-b137-0adc305c','13');
    
    /*Data for the table `sys_user` */
    
    insert  into `sys_user`(`id`,`usercode`,`username`,`password`,`salt`,`locked`) values 
    	('lisi','lisi','李四','bf07fd8bbc73b6f70b8319f2ebb87483','uiwueylm','0'),
    	('zhangsan','zhangsan','张三','cb571f7bd7a6f73ab004a70322b963d5','eteokues','0');
    
    /*Data for the table `sys_user_role` */
    
    insert  into `sys_user_role`(`id`,`sys_user_id`,`sys_role_id`) values 
    	('ebc8a441-c6f9-11e4-b137-0adc305c3f28','zhangsan','ebc8a441-c6f9-11e4-b137-0adc305c'),
    	('ebc9d647-c6f9-11e4-b137-0adc305c3f28','lisi','ebc9d647-c6f9-11e4-b137-0adc305c');
    
    /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
    查看对应权限模型的数据如下:
    sys_user  用户表数据

    sys_role  角色表

    sys_permission 权限表

    sys_user_role  用户角色关系表

    sys_role_permission  角色权限关系表

    开发环境

    JDK1.8
    MyEclipse
    技术架构:SpringMVC+Mybatis+jQuery easyUI

    系统工程架构


    系统登录

    系统登录相当于用户身份认证,用户登录成功,要在Session中记录用户的身份信息。
    操作流程:
    用户进入登录页面。
    输入用户名和密码进行登陆。
    进行用户名和密码校验。
    如果校验通过,在Session中记录用户身份信息。

    用户的身份信息

    创建专门类用于记录用户身份信息。
    /**
     * 用户身份信息,存入Session  由于Tomcat正常关闭时会将Session序列化的本地硬盘上,所以实现Serializable接口
     * @author liuxun
     *
     */
    public class ActiveUser implements Serializable {
    	private String userid; //用户id(主键)
    	private String usercode; // 用户账号
    	private String username; // 用户姓名
    	....
            ....
    }

    mapper

    mapper接口:根据用户账号查询用户(sys_user)信息 (使用逆向工程生成权限相关的PO类和mapper接口)
    如下所示:
      
    将生成的代码拷贝到项目中

    service(进行用户名和密码校验)

    接口功能:根据用户的身份和密码进行认证,如果认证通过,返回用户身份信息。
    认证过程:
    根据用户身份(账号)查询数据库,如果查询不到 则抛出用户不存在
    对输入的密码和数据库密码进行比对,如果一致,认证通过。
    新建权限管理Service接口 添加身份认证方法
    /**
     * 认证授权服务接口
     * @author liuxun
     *
     */
    public interface SysService {
    	//根据用户的身份和密码进行认证,如果认证通过,返回用户身份信息
    	public ActiveUser authenticat(String usercode,String password) throws Exception;
    	
    	//根据用户账号查询用户信息
    	public SysUser findSysUserByUserCode(String userCode) throws Exception;
            ......
    }
    方法实现:
    public class SysServiceImpl implements SysService {
    	@Autowired
    	private SysUserMapper sysUserMapper;
    
    	public ActiveUser authenticat(String usercode, String password) throws Exception {
    
    		/**
    		 * 认证过程: 根据用户身份(账号)查询数据库,如果查询不到则用户不存在 
    		 * 对输入的密码和数据库密码进行比对,如果一致则认证通过
    		 */
    		// 根据用户账号查询数据库
    		SysUser sysUser = this.findSysUserByUserCode(usercode);
    
    		if (sysUser == null) {
    			// 抛出异常
    			throw new CustomException("用户账号不存在");
    		}
    
    		// 数据库密码(MD5加密后的密码)
    		String password_db = sysUser.getPassword();
    
    		// 对输入的密码和数据库密码进行比对,如果一致,认证通过
    		// 对页面输入的密码进行MD5加密
    		String password_input_md5 = new MD5().getMD5ofStr(password);
    		if (!password_db.equalsIgnoreCase(password_input_md5)) {
    			//抛出异常
    			throw new CustomException("用户名或密码错误");
    		}
    		//得到用户id
    		String userid = sysUser.getId();
    		
    		//认证通过,返回用户身份信息
    		ActiveUser activeUser = new ActiveUser();
    		activeUser.setUserid(userid);
    		activeUser.setUsercode(usercode);
    		activeUser.setUsername(sysUser.getUsername());
    
    		return activeUser;
    	}
    
    	public SysUser findSysUserByUserCode(String userCode) throws Exception {
    		SysUserExample sysUserExample = new SysUserExample();
    		SysUserExample.Criteria criteria = sysUserExample.createCriteria();
    		criteria.andUsercodeEqualTo(userCode);
    
    		List<SysUser> list = sysUserMapper.selectByExample(sysUserExample);
    		if (list != null && list.size() > 0) {
    			return list.get(0);
    		}
    
    		return null;
    	}
       
           ......
    }
    配置Service,往类Service中使用@Autowire 需要注册Service 注册有两种方法(注解或配置文件),在架构时没有配置扫描Service  需要在配置文件中注册Service
    <!-- 认证和授权的Service -->
       <bean id="sysService" class="liuxun.ssm.service.impl.SysServiceImpl"></bean>

    controller(记录Session)

    //用户登录提交方法
    	@RequestMapping("/login")
    	public String login(HttpSession session,String randomcode,String usercode,String password) throws Exception{
    		// 校验验证码,防止恶性攻击
    		// 从Session中获取正确的验证码
    		String validateCode = (String) session.getAttribute("validateCode");
    		
    		//输入的验证码和Session中的验证码进行对比
    		if (!randomcode.equalsIgnoreCase(validateCode)) {
    			//抛出异常
    			throw new CustomException("验证码输入错误");
    		}
    		
    		//调用Service校验用户账号和密码的正确性
    		ActiveUser activeUser = sysService.authenticat(usercode, password);
    		
    		//如果Service校验通过,将用户身份记录到Session
    		session.setAttribute("activeUser", activeUser);
    		//重定向到商品查询页面
    		return "redirect:/first.action";
    	}

    用户认证拦截器

    anonymousURL.properties配置匿名URL

    配置可以匿名访问的URL


    编写身份认证拦截器

    //用于用户认证校验、用户权限校验
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            
    		//得到请求的url
    		String url = request.getRequestURI();
    		
    		//判断是否是公开地址
    		//实际开发中需要将公开地址配置在配置文件中
    		//从配置文件中取出可以匿名访问的URL
    		List<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");
    		for (String open_url : open_urls) {
    			if (url.indexOf(open_url)>=0) {
    				//如果是公开地址 则放行
    				return true;
    			}
    		}
    		
    		//判断用户身份在Session中是否存在
    		HttpSession session = request.getSession();
    		ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
    		//如果用户身份在session中存在则放行
    		if (activeUser!=null) {
    			return true;
    		}
    		//执行到这里拦截,跳转到登录页面,用户进行身份认证
    		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
    		
    		//如果返回false表示拦截器不继续执行handler,如果返回true表示放行
    		return false;
    	}

    配置认证拦截器

    <!-- 拦截器 -->
    	<mvc:interceptors>
    	    <mvc:interceptor>
    		   	<!-- 用户认证拦截 -->
    		   	<mvc:mapping path="/**"/>
    		   	<bean class="liuxun.ssm.controller.interceptor.LoginInterceptor"></bean>
    	    </mvc:interceptor>
    	</mvc:interceptors>

    用户授权

    commonURL.properties配置公用访问地址

    在此配置文件中配置公用访问地址,公用访问地址只需要通过用户认证,不需要对公用访问地址分配权限即可访问。

    获取用户权限范围的菜单

    思路:
    在用户认证时,认证通过,根据用户id从数据库获取用户权限范围内的菜单,将菜单的集合存储在Session中。
    编辑存储用户身份信息的类ActiveUser 如下所示:
    public class ActiveUser implements Serializable {
    	private String userid; //用户id(主键)
    	private String usercode; // 用户账号
    	private String username; // 用户姓名
    	
    	private List<SysPermission> menus; //菜单
            //......setter和getter方法
    }
    自定义权限Mapper
    因为使用逆向工程生成的Mapper是不建议去修改的 因为它的代码联系非常紧密,一旦修改错误 就会牵一发而动全身。所以需要自定义一个权限的Mapper(SysPermissionMapperCustom)
    SysPermissionMapperCustom.xml中添加根据用户id查询用户权限的菜单
    <!-- 根据用户id查询菜单 -->
    <select id="findMenuListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">
       SELECT 
    	  * 
    	FROM
    	  sys_permission 
    	WHERE TYPE = 'menu' 
    	  AND id IN 
    	  (SELECT 
    	    sys_permission_id 
    	  FROM
    	    sys_role_permission 
    	  WHERE sys_role_id IN 
    	    (SELECT 
    	      sys_role_id 
    	    FROM
    	      sys_user_role 
    	    WHERE sys_user_id = #{userid}))
    </select>
    SysPermissionMapperCustom .java接口中添加对应的方法
    public interface SysPermissionMapperCustom {
        //根据用户id查询菜单
    	public List<SysPermission> findMenuListByUserId(String userid) throws Exception;
      .......
    }
    在权限Service接口中添加对应的方法 在实现中注入SysPermissionMapperCustom
    SysServiceImpl.java中添加如下内容
    @Override
    	public List<SysPermission> findMenuListByUserId(String userid) throws Exception {
    		return sysPermissionMapperCustom.findMenuListByUserId(userid);
    	}

    获取用户权限范围的URL

    思路:
    在用户认证时,认证通过后,根据用户id从数据库中获取用户权限范围的URL,将URL的集合存储在Session中。
    修改ActiveUser 添加URL的权限集合
    public class ActiveUser implements Serializable {
    	private String userid; //用户id(主键)
    	private String usercode; // 用户账号
    	private String username; // 用户姓名
    	
    	private List<SysPermission> menus; //菜单
    	private List<SysPermission> permissions; //权限
    	//...setter和getter方法
    }
    SysPermissionMapperCustom .xml中添加根据用户id查询用户权限的URL
    <!-- 根据用户id查询URL -->
    <select id="findPermissionListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">
       SELECT 
    	  * 
    	FROM
    	  sys_permission 
    	WHERE TYPE = 'permission' 
    	  AND id IN 
    	  (SELECT 
    	    sys_permission_id 
    	  FROM
    	    sys_role_permission 
    	  WHERE sys_role_id IN 
    	    (SELECT 
    	      sys_role_id 
    	    FROM
    	      sys_user_role 
    	    WHERE sys_user_id = #{userid}))
    </select>
    SysPermissionMapperCustom .java接口中添加对应的方法
    //根据用户id查询权限URL
    	public List<SysPermission> findPermissionListByUserId(String userid) throws Exception;
    SysServiceImpl.java中添加如下内容
    @Override
    	public List<SysPermission> findPermissionListByUserId(String userid) throws Exception {
    		return sysPermissionMapperCustom.findPermissionListByUserId(userid);
    	}

    用户认证通过后取出菜单和URL放入Session

    修改权限SysServiceImpl中用户认证方法的代码
    //得到用户id
    		String userid = sysUser.getId();
    		//根据用户id查询菜单
    		List<SysPermission> menus = this.findMenuListByUserId(userid);
    		//根据用户id查询权限url
    		List<SysPermission> permissions = this.findPermissionListByUserId(userid);
    		
    		//认证通过,返回用户身份信息
    		ActiveUser activeUser = new ActiveUser();
    		activeUser.setUserid(userid);
    		activeUser.setUsercode(usercode);
    		activeUser.setUsername(sysUser.getUsername());
    		
            //放入权限范围的菜单和url
    		activeUser.setMenus(menus);
    		activeUser.setPermissions(permissions);

    菜单动态显示

    <c:if test="${activeUser.menus!=null }">
    				<ul>
    				<c:forEach items="${activeUser.menus }" var="menu">
    					<li><div>
    						<a title="${menu.name }" ref="1_1" href="#"
    							rel="${baseurl }/${menu.url }" icon="icon-log"><span
    							class="icon icon-log"> </span><span class="nav"><a href=javascript:addTab('${menu.name }','${baseurl }/${menu.url }')>${menu.name }</a></span></a>
    					</div></li>
    				</c:forEach>
    				</ul>
    			</c:if>

    授权拦截器

    public class PermissionInterceptor implements HandlerInterceptor{
    	//在执行handler之前执行的
    	//用于用户认证校验、用户权限校验
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            
    		//得到请求的url
    		String url = request.getRequestURI();
    		
    		//判断是否是公开地址
    		//实际开发中需要将公开地址配置在配置文件中
    		//从配置文件中取出可以匿名访问的URL
    		List<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");
    		for (String open_url : open_urls) {
    			if (url.indexOf(open_url)>=0) {
    				//如果是公开地址 则放行
    				return true;
    			}
    		}
    		
    		//从配置文件中获取公用访问url
    		List<String> common_urls = ResourcesUtil.getKeyList("commonURL");
    		//遍历公用地址 如果是公开地址则放行
    		for (String common_url : common_urls) {
    			if (url.indexOf(common_url)>0) {
    				//如果是公开,则放行
    				return true;
    			}
    		}
    		
    		//判断用户身份在Session中是否存在
    		HttpSession session = request.getSession();
    		ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
    		//从Session中取出权限范围的URL
    		List<SysPermission> permissions = activeUser.getPermissions();
    		for (SysPermission sysPermission : permissions) {
    			//权限url
    			String permission_url = sysPermission.getUrl();
    			if (url.indexOf(permission_url)>0) {
    				return true;
    			}
    		}
    		
    		//执行到这里拦截,跳转到无权访问的提示页面
    		request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response);
    		
    		//如果返回false表示拦截器不继续执行handler,如果返回true表示放行
    		return false;
    	}
       ......
    }

    配置授权拦截器

    注意:要将授权拦截器配置在用户认证拦截器的下边,这是因为SpringMVC拦截器的放行方法是顺序执行的,如果是Struts的话则正好相反。
    <!-- 拦截器 -->
    	<mvc:interceptors>
    	    <mvc:interceptor>
    		   	<!-- 用户认证拦截 -->
    		   	<mvc:mapping path="/**"/>
    		   	<bean class="liuxun.ssm.controller.interceptor.LoginInterceptor"></bean>
    	    </mvc:interceptor>
    	    <mvc:interceptor>
    	    	<!-- 资源拦截 -->
    	    	<mvc:mapping path="/**"/>
    	    	<bean class="liuxun.ssm.controller.interceptor.PermissionInterceptor"></bean>
    	    </mvc:interceptor>
    	</mvc:interceptors>
    运行测试:
    其关键代码如下:
    PO类ActiveUser.java 存放用户身份和权限信息的类
    package liuxun.ssm.po;
    
    import java.io.Serializable;
    import java.util.List;
    
    /**
     * 用户身份信息,存入Session  由于Tomcat正常关闭时会将Session序列化的本地硬盘上,所以实现Serializable接口
     * @author liuxun
     *
     */
    public class ActiveUser implements Serializable {
    	private static final long serialVersionUID = 1L;
    	
    	private String userid; //用户id(主键)
    	private String usercode; // 用户账号
    	private String username; // 用户姓名
    	
    	private List<SysPermission> menus; //菜单
    	private List<SysPermission> permissions; //权限
        // 提供对应setter和getter方法
        ......
    }
    自定义权限的Mapper 
    SysPermissionMapperCustom.java
    package liuxun.ssm.mapper;
    
    import java.util.List;
    import liuxun.ssm.po.SysPermission;
    import liuxun.ssm.po.SysPermissionExample;
    import org.apache.ibatis.annotations.Param;
    /**
     * 权限mapper
     * @author liuxun
     *
     */
    public interface SysPermissionMapperCustom {
        //根据用户id查询菜单
    	public List<SysPermission> findMenuListByUserId(String userid) throws Exception;
    	//根据用户id查询权限URL
    	public List<SysPermission> findPermissionListByUserId(String userid) throws Exception;
    }
    SysPermissionMapperCustom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="liuxun.ssm.mapper.SysPermissionMapperCustom">
    
    <!-- 根据用户id查询菜单 -->
    <select id="findMenuListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">
       SELECT 
    	  * 
    	FROM
    	  sys_permission 
    	WHERE TYPE = 'menu' 
    	  AND id IN 
    	  (SELECT 
    	    sys_permission_id 
    	  FROM
    	    sys_role_permission 
    	  WHERE sys_role_id IN 
    	    (SELECT 
    	      sys_role_id 
    	    FROM
    	      sys_user_role 
    	    WHERE sys_user_id = #{userid}))
    </select>
    <!-- 根据用户id查询URL -->
    <select id="findPermissionListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">
       SELECT 
    	  * 
    	FROM
    	  sys_permission 
    	WHERE TYPE = 'permission' 
    	  AND id IN 
    	  (SELECT 
    	    sys_permission_id 
    	  FROM
    	    sys_role_permission 
    	  WHERE sys_role_id IN 
    	    (SELECT 
    	      sys_role_id 
    	    FROM
    	      sys_user_role 
    	    WHERE sys_user_id = #{userid}))
    </select>
    </mapper>
    自定义权限的Service接口以及实现类
    SysService.java
    package liuxun.ssm.service;
    
    import java.util.List;
    
    import liuxun.ssm.po.ActiveUser;
    import liuxun.ssm.po.SysPermission;
    import liuxun.ssm.po.SysUser;
    
    /**
     * 认证授权服务接口
     * @author liuxun
     *
     */
    public interface SysService {
    	//根据用户的身份和密码进行认证,如果认证通过,返回用户身份信息
    	public ActiveUser authenticat(String usercode,String password) throws Exception;
    	
    	//根据用户账号查询用户信息
    	public SysUser findSysUserByUserCode(String userCode) throws Exception;
    	
    	//根据用户id查询权限范围内的菜单
    	public List<SysPermission> findMenuListByUserId(String userid) throws Exception;
    	
    	//根据用户id查询权限范围内的url
    	public List<SysPermission> findPermissionListByUserId(String userid) throws Exception;
    }
    
    SysServiceImpl.java
    package liuxun.ssm.service.impl;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    import liuxun.ssm.exception.CustomException;
    import liuxun.ssm.mapper.SysPermissionMapperCustom;
    import liuxun.ssm.mapper.SysUserMapper;
    import liuxun.ssm.po.ActiveUser;
    import liuxun.ssm.po.SysPermission;
    import liuxun.ssm.po.SysUser;
    import liuxun.ssm.po.SysUserExample;
    import liuxun.ssm.service.SysService;
    import liuxun.ssm.util.MD5;
    
    public class SysServiceImpl implements SysService {
    	@Autowired
    	private SysUserMapper sysUserMapper;
    	
    	@Autowired
    	private SysPermissionMapperCustom sysPermissionMapperCustom;
    
    	public ActiveUser authenticat(String usercode, String password) throws Exception {
    
    		/**
    		 * 认证过程: 根据用户身份(账号)查询数据库,如果查询不到则用户不存在 
    		 * 对输入的密码和数据库密码进行比对,如果一致则认证通过
    		 */
    		// 根据用户账号查询数据库
    		SysUser sysUser = this.findSysUserByUserCode(usercode);
    
    		if (sysUser == null) {
    			// 抛出异常
    			throw new CustomException("用户账号不存在");
    		}
    
    		// 数据库密码(MD5加密后的密码)
    		String password_db = sysUser.getPassword();
            
    		// 对输入的密码和数据库密码进行比对,如果一致,认证通过
    		// 对页面输入的密码进行MD5加密
    		String password_input_md5 = new MD5().getMD5ofStr(password);
    		if (!password_db.equalsIgnoreCase(password_input_md5)) {
    			//抛出异常
    			throw new CustomException("用户名或密码错误");
    		}
    		//得到用户id
    		String userid = sysUser.getId();
    		//根据用户id查询菜单
    		List<SysPermission> menus = this.findMenuListByUserId(userid);
    		//根据用户id查询权限url
    		List<SysPermission> permissions = this.findPermissionListByUserId(userid);
    		
    		//认证通过,返回用户身份信息
    		ActiveUser activeUser = new ActiveUser();
    		activeUser.setUserid(userid);
    		activeUser.setUsercode(usercode);
    		activeUser.setUsername(sysUser.getUsername());
    		
            //放入权限范围的菜单和url
    		activeUser.setMenus(menus);
    		activeUser.setPermissions(permissions);
    		
    		return activeUser;
    	}
    
    	public SysUser findSysUserByUserCode(String userCode) throws Exception {
    		SysUserExample sysUserExample = new SysUserExample();
    		SysUserExample.Criteria criteria = sysUserExample.createCriteria();
    		criteria.andUsercodeEqualTo(userCode);
    
    		List<SysUser> list = sysUserMapper.selectByExample(sysUserExample);
    		if (list != null && list.size() > 0) {
    			return list.get(0);
    		}
    
    		return null;
    	}
    	
    	@Override
    	public List<SysPermission> findMenuListByUserId(String userid) throws Exception {
    		return sysPermissionMapperCustom.findMenuListByUserId(userid);
    	}
    
    	@Override
    	public List<SysPermission> findPermissionListByUserId(String userid) throws Exception {
    		return sysPermissionMapperCustom.findPermissionListByUserId(userid);
    	}
    }
    登录控制器
    package liuxun.ssm.controller;
    
    import javax.servlet.http.HttpSession;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import liuxun.ssm.exception.CustomException;
    import liuxun.ssm.po.ActiveUser;
    import liuxun.ssm.service.SysService;
    
    /**
     * 登录和退出
     * @author liuxun
     *
     */
    @Controller
    public class LoginController {
        @Autowired
        private SysService sysService;
    	
    	//用户登录提交方法
    	@RequestMapping("/login")
    	public String login(HttpSession session,String randomcode,String usercode,String password) throws Exception{
    		// 校验验证码,防止恶性攻击
    		// 从Session中获取正确的验证码
    		String validateCode = (String) session.getAttribute("validateCode");
    		
    		//输入的验证码和Session中的验证码进行对比
    		if (!randomcode.equalsIgnoreCase(validateCode)) {
    			//抛出异常
    			throw new CustomException("验证码输入错误");
    		}
    		
    		//调用Service校验用户账号和密码的正确性
    		ActiveUser activeUser = sysService.authenticat(usercode, password);
    		
    		//如果Service校验通过,将用户身份记录到Session
    		session.setAttribute("activeUser", activeUser);
    		//重定向到商品查询页面
    		return "redirect:/first.action";
    	}
    	
    	//用户退出
    	@RequestMapping("/logout")
    	public String logout(HttpSession session) throws Exception{
    		//session失效
    		session.invalidate();
    		//重定向到商品查询页面
    		return "redirect:/first.action";
    	}
    }
    身份认证拦截器LoginInterceptor.java
    package liuxun.ssm.controller.interceptor;
    
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import liuxun.ssm.po.ActiveUser;
    import liuxun.ssm.util.ResourcesUtil;
    
    /**
     * 测试拦截器1
     * @author liuxun
     *
     */
    public class LoginInterceptor implements HandlerInterceptor{
    	//在执行handler之前执行的
    	//用于用户认证校验、用户权限校验
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            
    		//得到请求的url
    		String url = request.getRequestURI();
    		
    		//判断是否是公开地址
    		//实际开发中需要将公开地址配置在配置文件中
    		//从配置文件中取出可以匿名访问的URL
    		List<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");
    		for (String open_url : open_urls) {
    			if (url.indexOf(open_url)>=0) {
    				//如果是公开地址 则放行
    				return true;
    			}
    		}
    		
    		//判断用户身份在Session中是否存在
    		HttpSession session = request.getSession();
    		ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
    		//如果用户身份在session中存在则放行
    		if (activeUser!=null) {
    			return true;
    		}
    		//执行到这里拦截,跳转到登录页面,用户进行身份认证
    		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
    		
    		//如果返回false表示拦截器不继续执行handler,如果返回true表示放行
    		return false;
    	}
    
    	//在执行handler返回modelAndView之前执行
    	//如果需要向页面提供一些公用的数据或配置一些视图信息,使用此方法实现 从modelAndView入手
    	@Override
    	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
    			throws Exception {
    		System.out.println("HandlerInterceptor2...postHandle");
    	}
    
    	//执行handler之后执行此方法
    	//作为系统统一异常处理,进行方法执行性能监控,在preHandler中设置一个时间点 在afterCompletion设置一个时间点 二者时间差就是执行时长
    	//实现系统,统一日志记录
    	@Override
    	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception modelAndView)
    			throws Exception {
    		System.out.println("HandlerInterceptor2...afterCompletion");
    	}
    
    }
    资源授权拦截器PermissionInterceptor
    package liuxun.ssm.controller.interceptor;
    
    import java.security.acl.Permission;
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import liuxun.ssm.po.ActiveUser;
    import liuxun.ssm.po.SysPermission;
    import liuxun.ssm.util.ResourcesUtil;
    
    /**
     * 授权拦截器
     * @author liuxun
     *
     */
    public class PermissionInterceptor implements HandlerInterceptor{
    	//在执行handler之前执行的
    	//用于用户认证校验、用户权限校验
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            
    		//得到请求的url
    		String url = request.getRequestURI();
    		
    		//判断是否是公开地址
    		//实际开发中需要将公开地址配置在配置文件中
    		//从配置文件中取出可以匿名访问的URL
    		List<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");
    		for (String open_url : open_urls) {
    			if (url.indexOf(open_url)>=0) {
    				//如果是公开地址 则放行
    				return true;
    			}
    		}
    		
    		//从配置文件中获取公用访问url
    		List<String> common_urls = ResourcesUtil.getKeyList("commonURL");
    		//遍历公用地址 如果是公开地址则放行
    		for (String common_url : common_urls) {
    			if (url.indexOf(common_url)>0) {
    				//如果是公开,则放行
    				return true;
    			}
    		}
    		
    		//判断用户身份在Session中是否存在
    		HttpSession session = request.getSession();
    		ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
    		//从Session中取出权限范围的URL
    		List<SysPermission> permissions = activeUser.getPermissions();
    		for (SysPermission sysPermission : permissions) {
    			//权限url
    			String permission_url = sysPermission.getUrl();
    			if (url.indexOf(permission_url)>0) {
    				return true;
    			}
    		}
    		
    		//执行到这里拦截,跳转到无权访问的提示页面
    		request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response);
    		
    		//如果返回false表示拦截器不继续执行handler,如果返回true表示放行
    		return false;
    	}
    
    	//在执行handler返回modelAndView之前执行
    	//如果需要向页面提供一些公用的数据或配置一些视图信息,使用此方法实现 从modelAndView入手
    	@Override
    	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
    			throws Exception {
    		System.out.println("HandlerInterceptor2...postHandle");
    	}
    
    	//执行handler之后执行此方法
    	//作为系统统一异常处理,进行方法执行性能监控,在preHandler中设置一个时间点 在afterCompletion设置一个时间点 二者时间差就是执行时长
    	//实现系统,统一日志记录
    	@Override
    	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception modelAndView)
    			throws Exception {
    		System.out.println("HandlerInterceptor2...afterCompletion");
    	}
    
    }
    拦截器配置
    <!-- 拦截器 -->
    	<mvc:interceptors>
    	    <mvc:interceptor>
    		   	<!-- 用户认证拦截 -->
    		   	<mvc:mapping path="/**"/>
    		   	<bean class="liuxun.ssm.controller.interceptor.LoginInterceptor"></bean>
    	    </mvc:interceptor>
    	    <mvc:interceptor>
    	    	<!-- 资源拦截 -->
    	    	<mvc:mapping path="/**"/>
    	    	<bean class="liuxun.ssm.controller.interceptor.PermissionInterceptor"></bean>
    	    </mvc:interceptor>
    	</mvc:interceptors>
    使用URL拦截总结:
    使用基于URL拦截的权限管理方式,实现起来比较简单,不依赖框架使用过滤器或拦截器就可以实现
    弊端:需要将所有的URL全部配置起来,比较繁琐,不易维护,URL(资源)和权限表示方式不规范

    展开全文
  • Spring Security权限框架

    万次阅读 2019-05-06 21:40:05
    权限框架主要有? Spring Security Spring Security实战 1.搭建springbooot环境 2.只要能登录即可的例子 2.基于内存的权限设置 3.角色进行拦截 为什么需要权限管理? 安全性:误操作,人为破坏,...

    目录

     

     

     

    为什么需要权限管理?

    权限管理的核心是什么?

    权限框架主要有?

    Spring Security

    Spring Security实战

    1.搭建springbooot环境

    2.只要能登录即可的例子

    2.基于内存的权限设置

    3.角色进行拦截

     

     


     

     

    为什么需要权限管理?

    1. 安全性:误操作,人为破坏,数据泄露等
    2. 数据隔离:不同权限能看到及操作不同的数据
    3. 明确职责:运营,客服等不同角色,等级不同

    权限管理的核心是什么?

    1.用户-权限:人员少,功能固定,或特别简单的系统

    2.RBAC:用户-角色-权限  所有系统都适用

    权限框架主要有?

    1. Spring Security

    2.apache shiro

    本博客主要讲Spring Security 

     

    Spring Security

     

     

     

    主要是认证和验证

    Basic 认证:Basic 认证是HTTP 中非常简单的认证方式,因为简单,所以不是很安全,不过仍然非常常用。

     Digest 认证:客户端请求资源->服务器返回认证标示->客户端发送认证信息->服务器查验认证,如果成功则继续资源传送,否则直接断开连接。

    x.509认证:数字认证

    LDAP 认证:LDAP认证是通过WSS3.0加上轻量目录LDAP协议搭建的种认证方式,使用https加密传输,主要用于做文档管理。

    From 认证:表单认证

     

     下面使用springboot+Spring Security 实战下

    Spring Security实战

    1.搭建springbooot环境

    https://start.spring.io/  搭建springboot网站,选择如下两个依赖,我这里使用1.5.6.RELEASE的springboot

     

    搭建好了之后下载下来解压,导入IDEA 中

    运行项目,能成功启动即可,如下不报错,就说明这个工程没有问题。

    2.只要能登录即可的例子

     

    在主程序DemoApplication 中编写两个方法,一个是用来访问主页用( home()),一个是需要登录才能访问(hello()

    package com.su.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    @EnableAutoConfiguration
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        @RequestMapping("/")
        public String home() {
            return "您好,主页";
        }
    
        @RequestMapping("/hello")
        public String hello() {
            return "hello路径";
        }
    }
    

     

    新建一个方法SpringSecurityConfig  ,主要是用户进行权限设置的

     

     

    package com.su.demo;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    /**
     *主要是权限配置
     */
    @Configuration
    @EnableWebSecurity
    public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
        /**
         * 拦截下面的东西
         *
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/").permitAll() //主路径允许访问
                    .anyRequest().authenticated()  //验证
                    .and()
                    .logout().permitAll() //注销也是运行访问
                    .and()
                    .formLogin();
            http.csrf().disable();  //关闭csrf() 认证
        }
    
        /**
         * 不拦截下面这些资源
         *
         * @param web
         * @throws Exception
         */
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
        }
    }
    
    

    运行程序,效果:运行/ 允许访问  ,运行/hello 是需要被拦截的

     

    2.基于内存的权限设置

    在方法SpringSecurityConfig 中添加代码

    /**
     * 基于内存的验证:不需要用到数据库的情况
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //我们指定一个人这个人的用户:admin 密码:123456  角色:ADMIN
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("ADMIN");
    
    }
    

    当访问http://localhost:8080/hello 我们需要输入存在内存中的用户名密码

     

    3.角色进行拦截

    在方法DemoApplication 中添加代码

    @EnableGlobalMethodSecurity(prePostEnabled = true)//只有ADMIN 的角色才能访问

     

    /**
     * 只有ADMIN 的角色才能访问
     * @return
     */
    @PreAuthorize("hasRole('ROLE_ADMIN')")//必须用ROLE_xxx  才能识别你是做角色权限
    @RequestMapping("/roleAuth")
    public String role () {
        return "需要某个权限才能访问";
    }
    

    运行,当访问http://localhost:8080/roleAuth 时只有角色为ADMIN 的用户才能访问

     

     

     

    展开全文
  • 基于ASP.NET平台,通用权限管理系统,前台页面采用jquery EasyUI,界面美观大气。...设计结构采用标准三层设计,是一套非常成熟的权限框架程序,可直接用于大型系统基础框架快速开发,及程序员学习。
  • 一个十分简单的权限工具类。只需一个方法,便可以实现权限的授权,不同版本的兼容,以及回调的正确处理了。 对原有项目尽可能小的改动,方便已有项目的接入。使用方法示例如下: /*需要动态请求相机权限*/ ...
  • 权限框架介绍

    2013-02-22 23:40:30
    权限框架介绍ppt文档,系统对大家有所帮助,欢迎大家下载使用。
  • A013 Extjs FineUI通用权限框架
  • 普元权限框架ABFrame简介,权限结构描述,组织结构描述
  • springboot 2.x 整合 shiro 权限框架

    千次阅读 多人点赞 2020-09-04 09:06:43
    在实际项目中,经常需要用到角色权限区分,以此来为不同的角色赋予不同的权利,分配不同的任务。比如,普通用户只能浏览;会员可以浏览和评论;超级会员可以浏览、评论和看视频课等;实际应用场景很多。毫不夸张的说...

    在实际项目中,经常需要用到角色权限区分,以此来为不同的角色赋予不同的权利,分配不同的任务。比如,普通用户只能浏览;会员可以浏览和评论;超级会员可以浏览、评论和看视频课等;实际应用场景很多。毫不夸张的说,几乎每个完整的项目都会设计到权限管理。

    在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是由于 Spring Security 过于庞大和复杂,只要能满足业务需要,大多数公司还是会选择 Apache Shiro 来使用。

    一般来说,Spring Security 和 Shiro 的区别如下:

    Spring SecurityApache Shiro
    重量级的安全管理框架轻量级的安全管理框架
    概念复杂,配置繁琐概念简单、配置简单
    功能强大功能简单

    因此,这篇文章,阿淼首先会带大家了解 Apache Shiro ,然后和大家一起将 shiro 权限框架整合到 SpringBoot 中,以达到快速的实现整合权限管理的功能。

    走进 Apache Shiro

    官网认知

    照例又去官网扒了扒介绍:

    Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.
    Apache Shiro™是一个强大且易用的Java安全框架,能够用于身份验证、授权、加密和会话管理。Shiro拥有易于理解的API,您可以快速、轻松地获得任何应用程序——从最小的移动应用程序到最大的网络和企业应用程序。

    简而言之,Apache Shiro 是一个强大灵活的开源安全框架,可以完全处理身份验证、授权、加密和会话管理。

    Shiro能到底能做些什么呢?

    • 验证用户身份
    • 用户访问权限控制,比如:1、判断用户是否分配了一定的安全角色。2、判断用户是否被授予完成某个操作的权限
    • 在非 Web 或 EJB 容器的环境下可以任意使用Session API
    • 可以响应认证、访问控制,或者 Session 生命周期中发生的事件
    • 可将一个或以上用户安全数据源数据组合成一个复合的用户 “view”(视图)
    • 支持单点登录(SSO)功能
    • 支持提供“Remember Me”服务,获取用户关联信息而无需登录
      ···

    为什么今天还要使用Apache Shiro?

    对此,官方给出了详细的解释:http://shiro.apache.org/

    自2003年以来,框架环境发生了很大变化,因此今天仍然有充分的理由使用Shiro。实际上有很多原因。Apache Shiro是:

    • 易于使用 -易于使用是该项目的最终目标。应用程序安全性可能非常令人困惑和沮丧,并被视为“必要的邪恶”。如果您使它易于使用,以使新手程序员可以开始使用它,那么就不必再痛苦了。
    • 全面 -Apache Shiro声称没有其他具有范围广度的安全框架,因此它可能是满足安全需求的“一站式服务”。
    • 灵活 -Apache Shiro可以在任何应用程序环境中工作。尽管它可以在Web,EJB和IoC环境中运行,但并不需要它们。Shiro也不要求任何规范,甚至没有很多依赖性。
    • 具有Web功能 -Apache Shiro具有出色的Web应用程序支持,使您可以基于应用程序URL和Web协议(例如REST)创建灵活的安全策略,同时还提供一组JSP库来控制页面输出。
    • 可插拔 -Shiro干净的API和设计模式使它易于与许多其他框架和应用程序集成。您会看到Shiro与Spring,Grails,Wicket,Tapestry,Mule,Apache Camel,Vaadin等框架无缝集成。
    • 受支持 -Apache Shiro是Apache Software Foundation(Apache软件基金会)的一部分,该组织被证明以其社区的最大利益行事。项目开发和用户群体友好的公民随时可以提供帮助。如果需要,像Katasoft这样的商业公司也可以提供专业的支持和服务。

    Shiro 核心概念

    Apache Shiro 是一个全面的、蕴含丰富功能的安全框架。

    下图为描述 Shiro 功能的框架图:

    图片来源于网络

    如图所示,功能包括:

    • Authentication(认证):用户身份识别,通常被称为用户“登录”
    • Authorization(授权):访问控制。比如某个用户是否具有某个操作的使用权限。
    • Session Management(会话管理):特定于用户的会话管理,甚至在非web 或 EJB 应用程序。
    • Cryptography(加密):在对数据源使用加密算法加密的同时,保证易于使用。

    并且 Shiro 还有通过增加其他的功能来支持和加强这些不同应用环境下安全领域的关注点。

    特别是对以下的功能支持:

    • Web支持:Shiro 提供的 Web 支持 api ,可以很轻松的保护 Web 应用程序的安全。
    • 缓存:缓存是 Apache Shiro 保证安全操作快速、高效的重要手段。
    • 并发:Apache Shiro 支持多线程应用程序的并发特性。
    • 测试:支持单元测试和集成测试,确保代码和预想的一样安全。
    • “Run As”:这个功能允许用户假设另一个用户的身份(在许可的前提下)。
    • “Remember Me”:跨 session 记录用户的身份,只有在强制需要时才需要登录。

    注意: Shiro 不会去维护用户、维护权限,这些需要我们自己去设计/提供,然后通过相应的接口注入给 Shiro

    使用案例 Demo

    1.新建 maven 项目

    为方便我们初始化项目,Spring Boot给我们提供一个项目模板生成网站。

    • 1、打开浏览器,访问:https://start.spring.io/
    • 2、根据页面提示,选择构建工具,开发语言,项目信息等。

    2.导入 springboot 父依赖

    <parent>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-parent</artifactId>
    	<version>2.0.2.RELEASE</version>
    </parent>
    

    3.相关 jar 包

    web 包

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

    shiro-spring 包就是此篇文章的核心

    <dependency>
    	<groupId>org.apache.shiro</groupId>
    	<artifactId>shiro-spring</artifactId>
    	<version>1.4.0</version>
    </dependency>
    shiro 注解会用到 aop
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    数据库相关包使用的是mybatisplus
    <dependency>
    	<groupId>com.alibaba</groupId>
    	<artifactId>druid</artifactId>
    	<version>1.1.12</version>
    </dependency>
    <dependency>
    	<groupId>mysql</groupId>
    	<artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
    	<groupId>com.baomidou</groupId>
    	<artifactId>mybatis-plus-boot-starter</artifactId>
    	<version>3.1.0</version>
    </dependency>
    <dependency>
    	<groupId>com.baomidou</groupId>
    	<artifactId>mybatis-plus-generator</artifactId>
    	<version>3.1.0</version>
    </dependency>
    	<dependency>
    	<groupId>org.apache.velocity</groupId>
    	<artifactId>velocity-engine-core</artifactId>
    	<version>2.0</version>
    </dependency>
    

    4.数据库

    建表语句在项目中有,项目地址: https://github.com/mmzsblog/mmzsblog-util

    5.自定义 realm

    public class MyShiroRealm extends AuthorizingRealm {
    	@Autowired
    	private UserService userService;
    	@Autowired
    	private RoleService roleService;
    	@Autowired
    	private PermissionService permissionService;
    
    	@Override
    	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    
    		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    		// HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils
    		// .getSubject()).getServletRequest();//这个可以用来获取在登录的时候提交的其他额外的参数信息
    		String username = (String) principals.getPrimaryPrincipal();
    		// 受理权限
    		// 角色
    		Set<String> roles = new HashSet<String>();
    		Role role = roleService.getRoleByUserName(username);
    		System.out.println(role.getRoleName());
    		roles.add(role.getRoleName());
    		authorizationInfo.setRoles(roles);
    		// 权限
    		Set<String> permissions = new HashSet<String>();
    		List<Permission> querypermissions = permissionService.getPermissionsByRoleId(role.getId());
    		for (Permission permission : querypermissions) {
    			permissions.add(permission.getPermissionName());
    		}
    		authorizationInfo.setStringPermissions(permissions);
    		return authorizationInfo;
    	}
    
    	@Override
    	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
    			throws AuthenticationException {
    		String loginName = (String) authcToken.getPrincipal();
    		// 获取用户密码
    		User user = userService.getOne(new QueryWrapper<User>().eq("username", loginName));
    		if (user == null) {
    			// 没找到帐号
    			throw new UnknownAccountException();
    		}
    		String password = new String((char[]) authcToken.getCredentials());
    		String inpass = (new Md5Hash(password, user.getUsername())).toString();
    		if (!user.getPassword().equals(inpass)) {
    			throw new IncorrectCredentialsException();
    		}
    		// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
    		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(loginName, user.getPassword(),
    				ByteSource.Util.bytes(loginName), getName());
    
    		return authenticationInfo;
    	}
    
    }
    

    6.shiro 配置类

    @Configuration
    public class ShiroConfiguration {
    	private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
    
    	/**
    	 * Shiro的Web过滤器Factory 命名:shiroFilter
    	 */
    	@Bean(name = "shiroFilter")
    	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    		// Shiro的核心安全接口,这个属性是必须的
    		shiroFilterFactoryBean.setSecurityManager(securityManager);
    		//需要权限的请求,如果没有登录则会跳转到这里设置的url
    		shiroFilterFactoryBean.setLoginUrl("/login.html");
    		//设置登录成功跳转url,一般在登录成功后自己代码设置跳转url,此处基本没用
    		shiroFilterFactoryBean.setSuccessUrl("/main.html");
    		//设置无权限跳转界面,此处一般不生效,一般自定义异常
    		shiroFilterFactoryBean.setUnauthorizedUrl("/error.html");
    		Map<String, Filter> filterMap = new LinkedHashMap<>();
    		// filterMap.put("authc", new AjaxPermissionsAuthorizationFilter());
    		shiroFilterFactoryBean.setFilters(filterMap);
    		/*
    		 * 定义shiro过滤链 Map结构
    		 * Map中key(xml中是指value值)的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的
    		 * anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种
    		 * authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.
    		 * FormAuthenticationFilter
    		 */
    		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    		/*
    		 * 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边; authc:所有url都必须认证通过才可以访问;
    		 * anon:所有url都都可以匿名访问
    		 */
    		filterChainDefinitionMap.put("/login.html", "authc");
    		filterChainDefinitionMap.put("/login", "anon");
    		filterChainDefinitionMap.put("/js/**", "anon");
    		filterChainDefinitionMap.put("/css/**", "anon");
    		filterChainDefinitionMap.put("/logout", "logout");
    		filterChainDefinitionMap.put("/**", "authc");
    		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    		return shiroFilterFactoryBean;
    	}
    
    	/**
    	 * 权限管理
    	 */
    	@Bean
    	public SecurityManager securityManager() {
    		logger.info("=======================shiro=======================");
    		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    		securityManager.setRealm(MyShiroRealm());
    		// securityManager.setRememberMeManager(rememberMeManager);
    		return securityManager;
    	}
    
    	/**
    	 * Shiro Realm 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的
    	 */
    	@Bean
    	public MyShiroRealm MyShiroRealm() {
    		MyShiroRealm userRealm = new MyShiroRealm();
    		userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
    		return userRealm;
    	}
    
    	/**
    	 * 凭证匹配器 密码验证
    	 */
    	@Bean(name = "credentialsMatcher")
    	public HashedCredentialsMatcher hashedCredentialsMatcher() {
    		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    		// 散列算法:这里使用MD5算法;
    		hashedCredentialsMatcher.setHashAlgorithmName("md5");
    		// 散列的次数,比如散列两次,相当于 md5(md5(""));
    		hashedCredentialsMatcher.setHashIterations(1);
    		// storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码
    		hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
    		return hashedCredentialsMatcher;
    	}
    
    	/**
    	 * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
    	 */
    	@Bean
    	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
    		return authorizationAttributeSourceAdvisor;
    	}
    
    }
    

    7.测试类

    @RestController
    public class UserController {
    	@PostMapping("login")
    	public String name(String username, String password) {
    		String result = "已登录";
    		Subject currentUser = SecurityUtils.getSubject();
    		UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    		if (!currentUser.isAuthenticated()) {
    			try {
    				currentUser.login(token);// 会触发com.shiro.config.MyShiroRealm的doGetAuthenticationInfo方法
    				result = "登录成功";
    			} catch (UnknownAccountException e) {
    				result = "用户名错误";
    			} catch (IncorrectCredentialsException e) {
    				result = "密码错误";
    			}
    		}
    		return result;
    	}
    
    	@GetMapping("logout")
    	public void logout() {
    		Subject currentUser = SecurityUtils.getSubject();
    		currentUser.logout();
    	}
    
    	@RequiresPermissions("role:update")
    	@GetMapping("/role")
    	public String name() {
    		return "hello";
    	}
    
    	@RequiresPermissions("user:select")
    	@GetMapping("/role2")
    	public String permission() {
    		return "hello sel";
    	}
    
    }
    

    7.1 登录测试

    数据库账号(密码经过md5加盐加密)

    数据库账号

    账号错误测试

    密码错误测试

    账号正确测试

    登录成功界面

    7.2 权限测试

    权限测试1

    权限测试2

    8.说明

    8.1 无权限时的处理

    无权限时自定义了一个异常。所以,权限测试的时候没有权限就会提示配置的提示语 “没有权限”。

    @ControllerAdvice
    public class ShiroException {
    	@ExceptionHandler(value = UnauthorizedException.class)
    	@ResponseBody
    	public String name() {
    		return "没有权限";
    	}
    }
    

    8.2 角色权限测试与权限测试相同

    权限设置可在shiro配置类中shiro过滤链设置,也可用注解方式设置,本文使用注解方式。

    8.3 shiro 的 session 和 cache

    shiro 的 session 和 cache 管理可以自定义,本文用的是默认的,推荐自定义,方便管理。

    小结

    • Apache Shiro是Java的一个安全框架
    • Shiro是一个强大的简单易用的Java安全框架,主要用来更便捷的认证、授权、加密、会话管理、与Web集成、缓存等
    • Shiro使用起来小而简单
    • spring中有spring security ,是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。
    • shiro不依赖于spring,shiro不仅可以实现web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,
    • shiro属于轻量框架,越来越多企业项目开始使用shiro.

    参考:

    展开全文
  • Winform通用框架权限管理系统---------菜单,开发界面。 在csdn一篇博客中看到文章Winform通用框架权限管理系统,但是只有文章没有源码就是耍流氓。于是自己写了出来,可用于所有管理系统的开发框架。 软件的...
  • RBAC模型:权限框架入门必会

    千次阅读 2019-03-13 14:34:07
    大家在工作的日常经常会使用权限框架比如:Apache Shiro 、Spring Security等,这些框架的基础原理都是来自RBAC模型 1、什么是RBAC模型 RBAC(Role-Based Access Control )基于角色的访问控制。通过角色关联用户...
  • 自己用C#三层+EF+SqlServer2008R2写的winform权限框架带数据库可集成到任何需要权限控制的winform程序中。只需要吧自己写的dll放到程序根目录,如有不懂可以加我微信问我
  • Java权限框架合集

    2020-07-25 10:49:34
    权限控制是许多项目必备的模块。目前JavaEE中,Apache Shiro与Spring Security无疑是两大重要的权限框架,学好这两个框架对处理项目中的权限问题非常有帮助
  • Android6.0把权限分成正常权限和危险权限,AndroidManifest中声明的正常权限系统会自动授予,而危险权限则需要在使用的时候用户明确授予。 换句话说,就是Android6.0以上的系统在第一次使用危险权限的时候,需要向...
  • nodeJs用户权限管理框架

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 313,625
精华内容 125,450
关键字:

权限框架