权限 订阅
权限是指为了保证职责的有效履行,任职者必须具备的,对某事项进行决策的范围和程度。 展开全文
权限是指为了保证职责的有效履行,任职者必须具备的,对某事项进行决策的范围和程度。
信息
中文名
权限
外文名
privilege
词    性
名词
释    义
职能权利范围
权限含义
1、职能权利范围2、在法律规定的权限内。职权范围。权限是指为了保证职责的有效履行,任职者必须具备的,对某事项进行决策的范围和程度。它常常用“具有批准……事项的权限”来进行表达。
收起全文
精华内容
下载资源
问答
  • 权限漏洞:水平权限漏洞、垂直权限漏洞

    万次阅读 多人点赞 2019-07-31 19:21:31
    水平权限漏洞是指Web应用程序接收到用户请求时,没有判断数据的所属人,或者在判断数据所属人时是从用户提交的参数中获取了userid,导致攻击者可以自行修改userid修改不属于自己的数据。 漏洞示例: XXX/...

    水平权限漏洞是指Web应用程序接收到用户请求时,没有判断数据的所属人,或者在判断数据所属人时是从用户提交的参数中获取了userid,导致攻击者可以自行修改userid修改不属于自己的数据。

    漏洞示例:

    XXX/getAddress?id=1

    如上,攻击者修改addressId即可得到他人的address信息。开发容易习惯性的在生成CRUD(增查改删)表单(或AJAX请求)的时候根据认证过的用户身份来找出其有权限的被操作对象的id来提供入口,然后让用户提交请求,并根据这个id来操作相关对象。在处理CRUD请求时,都天真地默认只有有权限的用户才知道这个入口,进而才能操作相关对象,因此就不再校验权限了。可悲剧的是大多数对象的ID都被设置为自增整型,所以攻击者只要对相关id加1、减1、直至遍历,就可以操作其他用户所关联的对象了。

    修复方案:

    1、最正规的方案:把权限的控制转移到数据接口层中,避免出现select/update/delete ... where addressID=#addressID#的SQL语句,使用select/update/delete... where addressID=#addressID# and ownerId=#userId#来代替,要求web层在调用数据接口层的接口时额外提供userid,而这个userid在web层看来通常只能通过seesion来取到,以防用户造假。但这个方案的缺陷在于实现起来要改动底层的设计,所以不适合作为修复方案,更适合作为在最开始设计时的统一控制方案。

    2、最直接有效的修复方案:在web层的逻辑中做鉴权,检查提交CRUD请求的操作者(通过session或token等加密信息中得到,以防造假)与目标对象的权限所有者是否一致,如果不一致则阻断。这个方案实现成本低、能确保漏洞的修复质量,缺点是增加了一次查库操作。我之前一直用这种方案来对已发生的水平权限漏洞做紧急修复。

    另外的方法:

    1、可对ID加密

    2、使用UUID

    3、每一个信息增加一个发布人的字段,修改的人必须与发布的人为同一个人才可以访问

     

    垂直权限漏洞是指Web应用没有做权限控制,或仅仅在菜单上做了权限控制,导致恶意用户只要猜到了其他页面的URL,就可以访问或控制其他角色拥有的数据或页面,达到权限提升的目的。

    修复方案:

    只需要对url资源进行权限验证即可。

    展开全文
  • 一个免费的java权限后台管理系统框架

    千次下载 热门讨论 2015-01-23 17:52:35
    完整的功能应用,包括:后台权限、人员机构、参数代码、角色权限、上传文件、日志管理等内容。 您可以直接在其上面开发业务模块,具体下载和演示可访问:www.walkersoft.net。 开发文档整理中,很快会更新到网站中。...
  • 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(资源)和权限表示方式不规范

    展开全文
  • ASP.NET通用权限管理系统源代码(含文档、数据库)

    千次下载 热门讨论 2013-08-27 11:30:49
    ASP.NET通用权限管理系统源代码(含文档、数据库) 1.菜单导航管理 2.操作按钮 3.角色管理 4.部门管理 5.用户管理(用户权限) 6.用户组管理(设置成员,用户组权限) 7.系统配置(动态配置系统参数) 8.附加属性...
  • 在uni-app中如何配置权限 首先,我们先通过API了解,他对权限的需求,比如在上个帖子中 ===>>对APP后台静默更新升级对文件管理和文件下载权限的需求 当时我们使用了这个权限: android.permission.WRITE_...

    在uni-app中如何配置权限

    首先,我们先通过API了解,他对权限的需求,比如在上个帖子中   ===>>  对APP后台静默更新升级对文件管理和文件下载权限的需求

    当时我们使用了这个权限:

    android.permission.WRITE_EXTERNAL_STORAGE写入外部存储允许程序写入外部存储,如SD卡上写文件

    然后打开APP模块权限配置:在这个权限上打勾

    下面奉上所有的权限模块文档,便于查阅和搜索:

     

    权限名称描述
    android.permission.ACCESS_CHECKIN_PROPERTIES访问登记属性读取或写入登记check-in数据库属性表的权限
    android.permission.ACCESS_COARSE_LOCATION获取错略位置通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米
    android.permission.ACCESS_FINE_LOCATION获取精确位置通过GPS芯片接收卫星的定位信息,定位精度达10米以内
    android.permission.ACCESS_LOCATION_EXTRA_COMMANDS访问定位额外命令允许程序访问额外的定位提供者指令
    android.permission.ACCESS_MOCK_LOCATION获取模拟定位信息获取模拟定位信息,一般用于帮助开发者调试应用
    android.permission.ACCESS_NETWORK_STATE获取网络状态获取网络信息状态,如当前的网络连接是否有效
    android.permission.ACCESS_SURFACE_FLINGER访问Surface FlingerAndroid平台上底层的图形显示支持,一般用于游戏或照相机预览界面和底层模式的屏幕截图
    android.permission.ACCESS_WIFI_STATE获取WiFi状态获取当前WiFi接入的状态以及WLAN热点的信息
    android.permission.ACCOUNT_MANAGER账户管理获取账户验证信息,主要为GMail账户信息,只有系统级进程才能访问的权限
    android.permission.AUTHENTICATE_ACCOUNTS验证账户允许一个程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息
    android.permission.BATTERY_STATS电量统计获取电池电量统计信息
    android.permission.BIND_APPWIDGET绑定小插件允许一个程序告诉appWidget服务需要访问小插件的数据库,只有非常少的应用才用到此权限
    android.permission.BIND_DEVICE_ADMIN绑定设备管理请求系统管理员接收者receiver,只有系统才能使用
    android.permission.BIND_INPUT_METHOD绑定输入法请求InputMethodService服务,只有系统才能使用
    android.permission.BIND_REMOTEVIEWS绑定RemoteView必须通过RemoteViewsService服务来请求,只有系统才能用
    android.permission.BIND_WALLPAPER绑定壁纸必须通过WallpaperService服务来请求,只有系统才能用
    android.permission.BLUETOOTH使用蓝牙允许程序连接配对过的蓝牙设备
    android.permission.BLUETOOTH_ADMIN蓝牙管理允许程序进行发现和配对新的蓝牙设备
    android.permission.BRICK变成砖头能够禁用手机,非常危险,顾名思义就是让手机变成砖头
    android.permission.BROADCAST_PACKAGE_REMOVED应用删除时广播当一个应用在删除时触发一个广播
    android.permission.BROADCAST_SMS收到短信时广播当收到短信时触发一个广播
    android.permission.BROADCAST_STICKY连续广播允许一个程序收到广播后快速收到下一个广播
    android.permission.BROADCAST_WAP_PUSHWAP PUSH广播WAP PUSH服务收到后触发一个广播
    android.permission.CALL_PHONE拨打电话允许程序从非系统拨号器里输入电话号码
    android.permission.CALL_PRIVILEGED通话权限允许程序拨打电话,替换系统的拨号器界面
    android.permission.CAMERA拍照权限允许访问摄像头进行拍照
    android.permission.CHANGE_COMPONENT_ENABLED_STATE改变组件状态改变组件是否启用状态
    android.permission.CHANGE_CONFIGURATION改变配置允许当前应用改变配置,如定位
    android.permission.CHANGE_NETWORK_STATE改变网络状态改变网络状态如是否能联网
    android.permission.CHANGE_WIFI_MULTICAST_STATE改变WiFi多播状态改变WiFi多播状态
    android.permission.CHANGE_WIFI_STATE改变WiFi状态改变WiFi状态
    android.permission.CLEAR_APP_CACHE清除应用缓存清除应用缓存
    android.permission.CLEAR_APP_USER_DATA清除用户数据清除应用的用户数据
    android.permission.CWJ_GROUP底层访问权限允许CWJ账户组访问底层信息
    android.permission.CELL_PHONE_MASTER_EX手机优化大师扩展权限手机优化大师扩展权限
    android.permission.CONTROL_LOCATION_UPDATES控制定位更新允许获得移动网络定位信息改变
    android.permission.DELETE_CACHE_FILES删除缓存文件允许应用删除缓存文件
    android.permission.DELETE_PACKAGES删除应用允许程序删除应用
    android.permission.DEVICE_POWER电源管理允许访问底层电源管理
    android.permission.DIAGNOSTIC应用诊断允许程序到RW到诊断资源
    android.permission.DISABLE_KEYGUARD禁用键盘锁允许程序禁用键盘锁
    android.permission.DUMP转存系统信息允许程序获取系统dump信息从系统服务
    android.permission.EXPAND_STATUS_BAR状态栏控制允许程序扩展或收缩状态栏
    android.permission.FACTORY_TEST工厂测试模式允许程序运行工厂测试模式
    android.permission.FLASHLIGHT使用闪光灯允许访问闪光灯
    android.permission.FORCE_BACK强制后退允许程序强制使用back后退按键,无论Activity是否在顶层
    android.permission.GET_ACCOUNTS访问账户Gmail列表访问GMail账户列表
    android.permission.GET_PACKAGE_SIZE获取应用大小获取应用的文件大小
    android.permission.GET_TASKS获取任务信息允许程序获取当前或最近运行的应用
    android.permission.GLOBAL_SEARCH允许全局搜索允许程序使用全局搜索功能
    android.permission.HARDWARE_TEST硬件测试访问硬件辅助设备,用于硬件测试
    android.permission.INJECT_EVENTS注射事件允许访问本程序的底层事件,获取按键、轨迹球的事件流
    android.permission.INSTALL_LOCATION_PROVIDER安装定位提供安装定位提供
    android.permission.INSTALL_PACKAGES安装应用程序允许程序安装应用
    android.permission.INTERNAL_SYSTEM_WINDOW内部系统窗口允许程序打开内部窗口,不对第三方应用程序开放此权限
    android.permission.INTERNET访问网络访问网络连接,可能产生GPRS流量
    android.permission.KILL_BACKGROUND_PROCESSES结束后台进程允许程序调用killBackgroundProcesses(String).方法结束后台进程
    android.permission.MANAGE_ACCOUNTS管理账户允许程序管理AccountManager中的账户列表
    android.permission.MANAGE_APP_TOKENS管理程序引用管理创建、摧毁、Z轴顺序,仅用于系统
    android.permission.MTWEAK_USER高级权限允许mTweak用户访问高级系统权限
    android.permission.MTWEAK_FORUM社区权限允许使用mTweak社区权限
    android.permission.MASTER_CLEAR软格式化允许程序执行软格式化,删除系统配置信息
    android.permission.MODIFY_AUDIO_SETTINGS修改声音设置修改声音设置信息
    android.permission.MODIFY_PHONE_STATE修改电话状态修改电话状态,如飞行模式,但不包含替换系统拨号器界面
    android.permission.MOUNT_FORMAT_FILESYSTEMS格式化文件系统格式化可移动文件系统,比如格式化清空SD卡
    android.permission.MOUNT_UNMOUNT_FILESYSTEMS挂载文件系统挂载、反挂载外部文件系统
    android.permission.NFC允许NFC通讯允许程序执行NFC近距离通讯操作,用于移动支持
    android.permission.PERSISTENT_ACTIVITY永久Activity创建一个永久的Activity,该功能标记为将来将被移除
    android.permission.PROCESS_OUTGOING_CALLS处理拨出电话允许程序监视,修改或放弃播出电话
    android.permission.READ_CALENDAR读取日程提醒允许程序读取用户的日程信息
    android.permission.READ_CONTACTS读取联系人允许应用访问联系人通讯录信息
    android.permission.READ_FRAME_BUFFER屏幕截图读取帧缓存用于屏幕截图
    com.android.browser.permission.READ_HISTORY_BOOKMARKS读取收藏夹和历史记录读取浏览器收藏夹和历史记录
    android.permission.READ_INPUT_STATE读取输入状态读取当前键的输入状态,仅用于系统
    android.permission.READ_LOGS读取系统日志读取系统底层日志
    android.permission.READ_PHONE_STATE读取电话状态访问电话状态
    android.permission.READ_SMS读取短信内容读取短信内容
    android.permission.READ_SYNC_SETTINGS读取同步设置读取同步设置,读取Google在线同步设置
    android.permission.READ_SYNC_STATS读取同步状态读取同步状态,获得Google在线同步状态
    android.permission.REBOOT重启设备允许程序重新启动设备
    android.permission.RECEIVE_BOOT_COMPLETED开机自动允许允许程序开机自动运行
    android.permission.RECEIVE_MMS接收彩信接收彩信
    android.permission.RECEIVE_SMS接收短信接收短信
    android.permission.RECEIVE_WAP_PUSH接收Wap Push接收WAP PUSH信息
    android.permission.RECORD_AUDIO录音录制声音通过手机或耳机的麦克
    android.permission.REORDER_TASKS排序系统任务重新排序系统Z轴运行中的任务
    android.permission.RESTART_PACKAGES结束系统任务结束任务通过restartPackage(String)方法,该方式将在外来放弃
    android.permission.SEND_SMS发送短信发送短信
    android.permission.SET_ACTIVITY_WATCHER设置Activity观察其设置Activity观察器一般用于monkey测试
    com.android.alarm.permission.SET_ALARM设置闹铃提醒设置闹铃提醒
    android.permission.SET_ALWAYS_FINISH设置总是退出设置程序在后台是否总是退出
    android.permission.SET_ANIMATION_SCALE设置动画缩放设置全局动画缩放
    android.permission.SET_DEBUG_APP设置调试程序设置调试程序,一般用于开发
    android.permission.SET_ORIENTATION设置屏幕方向设置屏幕方向为横屏或标准方式显示,不用于普通应用
    android.permission.SET_PREFERRED_APPLICATIONS设置应用参数设置应用的参数,已不再工作具体查看addPackageToPreferred(String)介绍
    android.permission.SET_PROCESS_LIMIT设置进程限制允许程序设置最大的进程数量的限制
    android.permission.SET_TIME设置系统时间设置系统时间
    android.permission.SET_TIME_ZONE设置系统时区设置系统时区
    android.permission.SET_WALLPAPER设置桌面壁纸设置桌面壁纸
    android.permission.SET_WALLPAPER_HINTS设置壁纸建议设置壁纸建议
    android.permission.SIGNAL_PERSISTENT_PROCESSES发送永久进程信号发送一个永久的进程信号
    android.permission.STATUS_BAR状态栏控制允许程序打开、关闭、禁用状态栏
    android.permission.SUBSCRIBED_FEEDS_READ访问订阅内容访问订阅信息的数据库
    android.permission.SUBSCRIBED_FEEDS_WRITE写入订阅内容写入或修改订阅内容的数据库
    android.permission.SYSTEM_ALERT_WINDOW显示系统窗口显示系统窗口
    android.permission.UPDATE_DEVICE_STATS更新设备状态更新设备状态
    android.permission.USE_CREDENTIALS使用证书允许程序请求验证从AccountManager
    android.permission.USE_SIP使用SIP视频允许程序使用SIP视频服务
    android.permission.VIBRATE使用振动允许振动
    android.permission.WAKE_LOCK唤醒锁定允许程序在手机屏幕关闭后后台进程仍然运行
    android.permission.WRITE_APN_SETTINGS写入GPRS接入点设置写入网络GPRS接入点设置
    android.permission.WRITE_CALENDAR写入日程提醒写入日程,但不可读取
    android.permission.WRITE_CONTACTS写入联系人写入联系人,但不可读取
    android.permission.WRITE_EXTERNAL_STORAGE写入外部存储允许程序写入外部存储,如SD卡上写文件
    android.permission.WRITE_GSERVICES写入Google地图数据允许程序写入Google Map服务数据
    com.android.browser.permission.WRITE_HISTORY_BOOKMARKS写入收藏夹和历史记录写入浏览器历史记录或收藏夹,但不可读取
    android.permission.WRITE_SECURE_SETTINGS读写系统敏感设置允许程序读写系统安全敏感的设置项
    android.permission.WRITE_SETTINGS读写系统设置允许读写系统设置项
    android.permission.WRITE_SMS编写短信允许编写短信

     

     

    展开全文
  • android6.0 GPSdemo 动态申请权限
  • 用户权限设计方案

    千次下载 热门讨论 2013-05-28 16:03:42
    为了设计一套具有较强可扩展性的用户认证管理,需要建立用户、角色和权限等数据库表,并且建立之间的关系,提供的一种设计方案
  • android-support-v4 最新版本v4,可以解决Android6.0以上系统权限问题,内部有requestPermissions 等新的方法
  • PermissionX 1.5发布,支持申请Android特殊权限

    千次阅读 多人点赞 2021-07-24 11:55:16
    Hello大家早上好,说起PermissionX,其实我已经有段时间没有更新这个框架了。一是因为现在工作确实比较忙,没有过去那么多的闲暇时间来写开源项目,二是因为...而这些特殊权限并不属于Android运行时权限的一部分,所以

    本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每个工作日都有文章更新。

    Hello大家早上好,说起PermissionX,其实我已经有段时间没有更新这个框架了。一是因为现在工作确实比较忙,没有过去那么多的闲暇时间来写开源项目,二是因为,PermissionX的主体功能已经相当稳定,并不需要频繁对其进行变更。

    不过之前一直有朋友在反映,对于Android中的一些特殊权限申请,PermissionX并不支持。是的,PermissionX本质上只是对Android运行时权限API进行了一层封装,用于简化运行时权限申请的。而这些特殊权限并不属于Android运行时权限的一部分,所以PermissionX自然也是不支持的。

    但是特殊权限却是我们这些开发者们可能经常要与之打交道的一部分,它们并不难写,但是每次去写都感觉很繁琐。因此经慎重考虑之后,我决定将几个比较常用的特殊权限纳入PermissionX的支持范围。那么本篇文章我们就来看一看,对于这几个常见的特殊权限,使用PermissionX和不使用PermissionX的写法有什么不同之处。

    对于还从来没有了解过PermissionX的朋友们,可以通过我编写的《PermissionX权限系列专栏》逐步进行学习,将帮助你很好地理解和使用这个框架。

    什么是特殊权限?

    事实上,Android的权限机制也是经历过长久的迭代的。在6.0系统之前,Google将权限机制设计的比较简单,你的应用程序需要用到什么权限,只需要在AndroidManifest.xml文件中声明一下就可以了。

    但是从6.0系统开始,Android引入了运行时权限机制。Android将常用的权限大致归成了几类,一类是普通权限,一类是危险权限,一类是特殊权限。

    普通权限指的是那些不会直接威胁到用户的安全和隐私的权限,这种权限和过去一样,只需要在AndroidManifest.xml文件中声明一下就可以了,不需要做任何特殊处理。

    危险权限则表示那些可能会触及用户隐私或者对设备安全性造成影响的权限,如获取设备联系人信息、定位设备的地理位置等。这部分权限需要通过代码进行申请,并要用户手动同意才可获得授权。PermissionX库主要就是处理的这种权限的申请。

    而特殊权限则更加少见,Google认为这种权限比危险权限还要敏感,因此不能仅仅让用户手动同意就可以获得授权,而是需要让用户到专门的设置页面去手动对某一个应用程序授权,该程序才能使用这个权限。

    不过相比于危险权限,特殊权限没有非常固定的申请方式,每个特殊权限可能都要使用不同的写法才行,这也导致申请特殊权限比申请危险权限还要繁琐。

    从1.5.0版本开始,PermissionX对最常用的几个特殊权限进行了支持。正如刚才所说,特殊权限没有固定的申请方式,因此PermissionX也是针对于这几个特殊权限一个一个去适配并支持的。如果你发现你需要申请的某个特殊权限还没有被PermissionX支持,也可以向我提出需求,我会考虑在接下来的版本中加入。

    jcenter的现状

    在过去,我们发布开源库通常都是发布到jcenter上的,但是相信大家现在都已经知道了,jcenter即将停止服务,具体可以参考我的这篇文章 浅谈JCenter即将被停止服务的事件

    目前的jcenter处在一个半废弃的边缘,虽然还可以正常从jcenter下载开源库,但是已经不能再向jcenter发布新的开源库了。而在明年2月1号之后,下载服务也会被关停。

    所以,以后要想再发布开源库我们只能选择发布到其他仓库,比如现在Google推荐我们使用Maven Central。

    于是,从1.5.0版本开始,PermissionX也会将库发布到Maven Center上,之前的老版本由于迁移价值并不大,所以我也不想再耗费经历做迁移了。1.5.0之前的版本仍然保留在jcenter上,提供下载服务直到明年的2月1号。

    而关于如何将库发布到Maven Central,请参考 再见JCenter,将你的开源库发布到MavenCentral上吧

    那么我们还是先回到PermissionX。

    请求特殊权限

    Android里具体有哪些特殊权限呢?

    说实话,这个我也不太清楚。我所了解的特殊权限基本都是因为需要用到了,然后发现这个权限即不属于普通权限,也不属于危险权限,要用一种更加特殊的方式去申请,才知道原来这是一个特殊权限。

    因此,PermissionX 1.5.0版本中对特殊权限的支持,也就仅限于我知道的,以及从网友反馈得来的几个最为常用的特殊权限。

    一共是以下3个:

    1. 悬浮窗
    2. 修改设置
    3. 管理外部存储

    接下来我就分别针对这3个特殊权限做一下更加详细的介绍。


    悬浮窗

    悬浮窗功能在不少应用程序中使用得非常频繁,因为你可能总有一些内容是要置顶于其他内容之上显示的,这个时候用悬浮窗来实现就会非常方便。

    当然,如果你只是在自己的应用内部实现悬浮窗功能是不需要申请权限的,但如果你的悬浮窗希望也能置顶于其他应用程序的上方,这就必须得要申请权限了。

    悬浮窗的权限名叫做SYSTEM_ALERT_WINDOW,如果你去查一下这个权限的文档,会发现这个权限的申请方式比较特殊:

    按照文档上的说法,从Android 6.0系统开始,我们在使用SYSTEM_ALERT_WINDOW权限前需要发出一个action为Settings.ACTION_MANAGE_OVERLAY_PERMISSION的Intent,引导用户手动授权。另外我们还可以通过Settings.canDrawOverlays()这个API来判断用户是否已经授权。

    因此,想要申请悬浮窗权限,自然而然就可以写出以下代码:

    if (Build.VERSION.SDK_INT >= 23) {
        if (Settings.canDrawOverlays(context)) {
            showFloatView()
        } else {
            val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
            startActivity(intent)
        }
    } else {
        showFloatView()
    }
    

    看上去也不复杂嘛。

    确实,但是它麻烦的点主要在于,它的请求方式是脱离于一般运行时权限的请求方式的,因此得要为它额外编写独立的权限请求逻辑才行。

    而PermissionX的目标就是要弱化这种独立的权限请求逻辑,减少差异化代码编写,争取使用同一套API来实现对特殊权限的请求。

    如果你已经比较熟悉PermissionX的用法了,那么以下代码你一定不会陌生:

    PermissionX.init(activity)
        .permissions(Manifest.permission.SYSTEM_ALERT_WINDOW)
        .onExplainRequestReason { scope, deniedList ->
            val message = "PermissionX需要您同意以下权限才能正常使用"
            scope.showRequestReasonDialog(deniedList, message, "Allow", "Deny")
        }
        .request { allGranted, grantedList, deniedList ->
            if (allGranted) {
                Toast.makeText(activity, "所有申请的权限都已通过", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(activity, "您拒绝了如下权限:$deniedList", Toast.LENGTH_SHORT).show()
            }
        }
    

    可以看到,这就是最标准的PermissionX的正常用法,但是我们在这里却用来请求了悬浮窗权限。也就是说,即使是特殊权限,在PermissionX中也可以用普通的方式去处理。

    另外不要忘记,所有申请的权限都必须在AndroidManifest.xml进行注册才行:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.permissionx.app">
        
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    
    </manifest>
    

    那么运行效果是什么样的呢?我们来看看吧:

    可以看到,PermissionX还自带了一个权限提示框,友好地告知用户我们需要悬浮窗权限,引导用户去手动开启。


    修改设置

    了解了悬浮窗权限的请求方式之后,接下来我们就可以快速过一下修改设置权限的请求方式了,因为它们的用法是完全一样的。

    修改设置的权限名叫WRITE_SETTINGS,如果我们去查看一下它的文档,你会发现它和刚才悬浮窗权限的文档简直如出一辙:

    同样是从Android 6.0系统开始,在使用WRITE_SETTINGS权限前需要先发出一个action为Settings.ACTION_MANAGE_WRITE_SETTINGS的Intent,引导用户手动授权。然后我们还可以通过Settings.System.canWrite()这个API来判断用户是否已经授权。

    所以,如果是自己手动申请这个权限,相信你已经知道要怎么写了。

    那么用PermissionX申请的话应该要怎么写呢?这个当然就更简单了,只需要把要申请的权限替换一下即可,其他部分都不用作修改:

    PermissionX.init(activity)
        .permissions(Manifest.permission.WRITE_SETTINGS)
        ...
    

    当然,不要忘记在AndroidManifest.xml中注册权限:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.permissionx.app">
        
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    
    </manifest>
    

    运行一下,效果如下图所示:


    管理外部存储

    管理外部存储权限也是一种特殊权限,它可以允许你的App拥有对整个SD卡进行读写的权限。

    有些朋友可能会问,SD卡本来不就是可以全局读写的吗?为什么还要再申请这个权限?

    那你一定是没有了解Android 11上的Scoped Storage功能。从Android 11开始,Android系统强制启用了Scoped Storage,所有App都不再拥有对SD卡进行全局读写的权限了。

    关于Scoped Storage的更多内容,可以参考我的这篇文章 Android 11新特性,Scoped Storage又有了新花样

    但是如果有的应用就是要对SD卡进行全局读写该怎么办呢(比如说文件浏览器)?

    不用担心,Google仍然还是给了我们一种解决方案,那就是请求管理外部存储权限。

    这个权限是Android 11中新增的,为的就是应对这种特殊场景。

    那么这个权限要怎么申请呢?我们还是先来看一看文档:

    大致可以分为几步吧:

    第一,在AndroidManifest.xml中声明MANAGE_EXTERNAL_STORAGE权限。

    第二,发出一个action为Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION的Intent,引导用户手动授权。

    第三,调用Environment.isExternalStorageManager()来判断用户是否已授权。

    传统请求权限的写法我就不再演示了,使用PermissionX来请求的写法仍然也还是差不多的。只不过要注意,因为MANAGE_EXTERNAL_STORAGE权限是Android 11系统新加入的,所以我们也只应该在Android 11以上系统去请求这个权限,代码如下所示:

    if (Build.VERSION.SDK_INT >= 30) {
        PermissionX.init(this)
            .permissions(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
            ...
    }
    

    AndroidManifest.xml中的权限如下:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.permissionx.app">
        
        <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    
    </manifest>
    

    运行一下程序,效果如下图所示:

    这样我们就拥有全局读写SD卡的权限了。

    另外PermissionX还有一个特别方便的地方,就是它可以一次性申请多个权限。假如我们想要同时申请悬浮窗权限和修改设置权限,只需要这样写就可以了:

    PermissionX.init(activity)
        .permissions(Manifest.permission.SYSTEM_ALERT_WINDOW, Manifest.permission.WRITE_SETTINGS)
        ...
    

    运行效果如下图所示:

    当然你也可以将特殊权限与普通运行时权限放在一起申请,PermissionX对此也是支持的。只有当所有权限都请求结束时,PermissionX才会将所有权限的请求结果一次性回调给开发者。

    其实除了以上3种特殊权限之外,PermissionX还额外支持一种特殊权限,就是后台定位权限。只不过这个权限并不是在1.5.0版本中才支持的,而是1.2版本就开始支持了,感兴趣的朋友可以参考这篇文章 PermissionX现在支持Java了!还有Android 11权限变更讲解

    如何升级

    关于PermissionX新版本的内容变化就介绍到这里,升级的方式非常简单,修改一下dependencies当中的版本号即可:

    repositories {
      google()
      mavenCentral()
    }
    
    
    dependencies {
        implementation 'com.guolindev.permissionx:permissionx:1.5.0'
    }
    

    注意现在一定要使用mavenCentral仓库,而不能再使用jcenter了。

    如果你对PermissionX的源码感兴趣,可以访问PermissionX的项目主页:

    https://github.com/guolindev/PermissionX

    另外,本篇文章主要介绍的是PermissionX 1.5.0版本的新特性。如果你之前并没有接触过PermissionX,可以通过我编写的《PermissionX权限系列专栏》逐步进行学习,里面有非常详尽的用法讲解。


    如果想要学习Kotlin和最新的Android知识,可以参考我的新书 《第一行代码 第3版》点击此处查看详情


    关注我的技术公众号,每天都有优质技术文章推送。

    微信扫一扫下方二维码即可关注:

    展开全文
  • 权限系统的基本概念和架构

    万次阅读 热门讨论 2020-12-21 19:33:06
    权限系统是我们在系统设计和应用中一种非常常见的系统。一般来说权限系统的功能分为认证和授权两种。认证就非常简单的,验证完用户名密码就算认证成功,而授权里面的套路就很多了,本文将会详细讲解权限系统中的一些...
  • 数据权限设计研究-行数据权限

    万次阅读 2019-01-17 19:22:56
    数据权限设计研究-行数据权限关于权限设计功能权限数据权限前提数据分类几种场景设计方案与思路映射表提供过滤sql的方法测试实际应用查询新增修改删除修改数据的私有,公开,部门属性私有改为部门私有改为公开部门改...
  • 最全的权限系统设计

    千次阅读 多人点赞 2020-03-22 20:47:53
    权限管理是公司数据安全的重要保证,针对不同的岗位,不同的级别看到的数据是不一样的,操作数据的限制也是不一样的。比如涉及到资金的信息只开放给财务的相关岗位,涉及到配置的信息只开放给运营的相关岗位,这样各...
  • Android开发之 permission动态权限获取

    万次阅读 多人点赞 2019-08-19 10:57:20
    权限查看:戳这里 在文章最后附上DEMO DEMO效果: 一、说明: 1、支持单个权限、多个权限、单个权限组、多个权限组请求 2、不指定权限则自动获取清单文件上的危险权限进行申请 3、如果动态申请的权限没有...
  • 原来在Android中请求权限也可以有这么棒的用户体验

    万次阅读 多人点赞 2020-09-15 07:28:00
    然而随着我发现这个项目不仅有学习的价值,还可以真正投入到实际项目的使用当中,于是后面又对PermissionX进行了多个版本的迭代,目前已经成为了一个非常稳定和方便的权限请求库。 在1.3.0版本当中,PermissionX...
  • MySQL查看用户权限权限管理

    万次阅读 多人点赞 2019-10-22 15:47:55
    一、 MySQL权限级别介绍 全局——可以管理整个MySQL 库——可以管理指定的数据库 表——可以管理指定数据库的指定表 字段——可以管理指定数据库的指定表的指定字段 权限存储在mysql库的user, db, tables_...
  • Android运行时权限终极方案,用PermissionX吧

    万次阅读 多人点赞 2020-05-19 08:03:13
    没有人愿意编写处理Android运行时权限的代码,因为它真的太繁琐了。 这是一项没有什么技术含量,但是你又不得不去处理的工作,因为不处理它程序就会崩溃。但如果处理起来比较简单也就算了,可事实上,Android提供给...
  • 权限管理系统源码合集【含数据库】

    千次下载 热门讨论 2012-11-20 08:02:35
    权限系统源码合集【含数据库】,很具有参考价值,推荐给大家。 struts2权限管理系统 通用权限管理系统设计篇.doc 固定资产管理系统项目 Jaoso新闻文章发布系统final+Struts+Spring+Hibernate java web 系统权限...
  • 基于springsecurity+springmvc+spring+hibernate的权限管理系统,实现资源、用户、权限、角色的增删改查,角色-资源管理,用户-角色管理等基础功能,可以作为springmvc+spring+hibernate的增删改查入门项目,也可以...
  • NTFS权限详解

    万次阅读 2019-06-10 16:29:00
    NTFS权限是作为一个Windows管理员必备的知识,许多经验丰富的管理员都能够很熟悉地对文件、文件夹、注册表项等进行安全性的权限设置,包括完全控制、修改、只读等。而谈论NTFS权限这个话题也算是老生常谈了,但是...
  • java权限管理系统的jar包

    千次下载 热门讨论 2012-11-10 10:42:19
    java权限管理系统的jar包配合http://www.oschina.net/code/snippet_59256_15087使用。
  • 通用数据权限的设计思路

    万次阅读 2020-01-02 09:25:30
    接着上个襄阳项目的需要, 目前的项目情况是,一期已经把功能权限做完了,可以对不同用户的不同权限功能做到限制,现在需要做数据的权限,不同的用户看到不同的数据。 根据目前的调研情况,有两种数据级别权限设计...
  • 权限、角色、用户:
  • RBAC权限模型

    万次阅读 多人点赞 2019-06-01 11:46:53
     RBAC 是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予...
  • 浅谈权限(功能权限&数据权限

    千次阅读 2020-02-28 11:38:18
    一般企业上的权限部分,都是区分为功能权限和数据权限。 功能权限: 功能权限,就是用户登录后,能看到哪些菜单,能看到哪些按钮,能执行哪些操作的权限。 一般,功能权限,已经都有很成熟的业内方案和框架了。 比如...
  • Linux下的用户、组和权限

    万次阅读 多人点赞 2018-08-30 22:57:40
    目录 一:用户和组信息的查看 查看用户信息 ... 查看组信息 ...ACL控制权限setfacl 、getfacl Umask、Suid、Sgid、粘滞位 四:Linux中的sudo、sudo -i、su、su -命令 相关文章:Linux用户方面的加固...
  • Spring Security 中的四种权限控制方式

    万次阅读 多人点赞 2020-06-17 09:21:49
    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Security 提供的方式做授权,也可以自定义授权...
  • 一、文件基本权限 1-1.基本权限的修改 -rw-r--r--  - 第一个"-"表示文件类型(- 文件,d 目录,l 软链接文件)  - rw- r-- r--  u所有者 g所属组 o其它人 其中r读,w写,x执行 (1).chmod [选项] ...
  • Android权限管理

    万次阅读 2019-07-17 12:39:52
    Android权限管理(PermissionsDispatcher框架使用)简述一、Android权限二、6.0以上权限管理 简述 由于对于安全考虑,Android对于权限的管理更加的严谨,以6.0位界分为两种处理方式:6.0以下系统还是保持旧的处理...
  • 菜单访问权限控制 配置helloword菜单【系统管理】-【菜单管理】 其中前端组件配置相对src/views/目录下的 目录名+文件名 例如页面src/views/jeecg/helloworld.vue 前端组件配置 jeecg/helloworld 用户角色授权...
  • Oracle数据库用户权限查询和一些查看操作(汇总) 2018年07月22日 20:32:38 茶木君 阅读数:1222 标签: oracle 更多 个人分类: oracle dba权限:user为有dba权限的账号,如sys,system,或者是已经被授予...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,598,724
精华内容 1,039,489
关键字:

权限