精华内容
下载资源
问答
  • 太久没写了,今天补一篇,本篇无实际代码,主要是设计思路。 关于JWT:在我所开发的系统中用户Token都是有意义的,都会携带部分数据,不过多用于userId ...好处是简单,但是权限写在逻辑里面了。改权限

    太久没写了,今天补一篇,本篇无实际代码,主要是设计思路。

    关于JWT:在我所开发的系统中用户Token都是有意义的,都会携带部分数据,不过多用于userId

    个人的权限系统使用历程:

    基于Security(不加表、角色放在Token中)

    • 注解验证(乱七八糟)
      使用Spring Security框架,将用户角色ROLE_USER写在account表中,UserDetailsService的实现方法中封装UserDetails返回,然后在接口上添加注解进行权限校验
      好处是简单,但是权限写在逻辑里面了。改权限就要发版本,小系统可以这样干
    • 请求地址前缀验证(分模块)
      顾名思义,按照角色划分接口地址,类似于微服务模块拆分,但是这个纯粹就是为了权限验证拆。而且说实话也不好升级。

    RBAC模型

    用户表、角色表、功能表、接口表、关联表
    在这里插入图片描述
    凑活看。不过后面的很多思路都是基于这个表结构的。

    • RBAC数据库
      实现AccessDecisionManager接口

      FilterInvocation filterInvocation = (FilterInvocation) object;
      Set<String> uris = smsAccountRoleMapper.uris((String) authentication.getPrincipal());
      if (uris.contains(filterInvocation.getRequestUrl())) {
          return;
      } else {
          log.info("当前请求路径:[{}]用户权限为:[{}]", filterInvocation.getRequestUrl(), uris);
          throw new AccessDeniedException("权限不足");
      }
      

      到这里就已经实现接口权限动态配置了,但是同时到此也全都是没营养的废话,下面开始更经典的。

    • 使用Redis+JWT
      Redis用于存储JWT、JWT用来存储用户标识
      实现AuthorizationServerTokenServicescreateAccessTokenrefreshAccessToken方法,不需要实现TokenStore,直接写在MyTokenService里就行、就是一堆Token生成存储逻辑、从JWT的实现类里面拷贝一部分,再拷贝一部分Redis的就组合成了。

      技巧:以下所有存储,Redis有效期设置尽量比真实的有效期短1小时,防止Redis验证通过而Token解析失败

      前缀含义
      UNAME_TO_ACCESS用户标识>>>accessToken、主要用于用户封号冻结时删除Token及单设备登录限制
      ACCESS_TO_USERaccessToken >>>userId、鉴于Token为JWT生成,所以此处仅用于验证Token真实性
      ACCESS_TO_REFRESHaccessToken >>>refreshToken 、账号冻结时删除当前账号所有有关的Token信息
      REFRESH_TO_ACCESSrefreshToken >>> accessToken、刷新令牌仅可以使用一次、且用完之后需要删除旧的accessToken
      REFRESHrefreshToken信息、用于刷新令牌

      验证逻辑
      1、开放性接口直接过
      2、需要登录的由Redis负责校验是否为真实有效的Token
      3、需要进行权限校验的依靠数据库RBAC关系进行查询校验。

    • 微服务
      其实微服务和前面的一样,认证中心发放Token,网关验证鉴权、所有的逻辑基本一致

    • 前端按钮验证
      在这里要安利一个开源项目:若依,给了我很多启发。
      上文表结构接口表中有一个字段为前端验证key,具体使用方式为后端在用户登录之后返给前端一个Set集合,前端在组件中封装一个标签,类似v-if,参数为这个按钮的验证key,如果Set集合中有就显示,没有就不显示按钮。
      下图是若依的验证逻辑,考虑的非常周到,一个按钮可能对应多个接口:
      在这里插入图片描述
      建议:尽量和后端接口名保持一致,因为后端接口你不可能提供两个相同的(尽量使用PostMapping

    • 前端页面验证
      页面相较于按钮复杂之处在于后端的一个接口会在多个页面调用且一个页面会调用后端多个接口,所以后端提供路由配置就显得不是那么方便,所以我的思路是:前端知道当前页面会调用哪些接口,而且也知道哪些接口有权限验证,同时考虑到前端某些数据可能今天在这里展示,明天就换位置了,所以将页面级的路由交于前端自行校验,具体逻辑为:
      1、当前页面存在开放性接口,如查询,那么直接展示
      2、当前页面所有接口都需要权限,那么验证后端返回的Set集合中是否和当前页面的接口验证key存在交集,如果有展示,如果没有隐藏

    DBAC模型

    顾名思义:同一个接口,不同的人访问看到的数据是不一样的,这个不一样不是指看到的自己的数据不一样,而是同样一个页面,你只能看自己的,老师能看班级的,校长能看全校的。

    数据权限一定要根据系统实际使用进行设计,虽然有某些通用的设计方案,但是如果直接拿过来使用而不加以设计那么一定会面临性能问题。

    • 统一权限
      某人对系统的操作等级是固定的,只在角色变更时变化,那么可以使用若依的那套实现方式,MyBatis拦截器的方式,然后判断用户权限等级拼接SQL后缀、不过若依那一套简单,SQL基本固定,因为他的部门角色是基础实现。
    • 拆分权限
      一个用户对于系统中的不同接口的访问权限是不同的,不单单是部门的问题(例如一个部门的部长犯了错误,公司让他回家反省,那么他还是部长,但是可能他再登录系统就只能看自己的数据了)
      思路:将前端的验证思路搬到后端,在MyBatis接口上添加注解,在拦截器中判断当前用户对于当前SQL的权限等级是什么,查询出不同的SQL后缀拼接到查询语句中。
      在这里插入图片描述
      知道用户、mapper接口、那么就能查看对应的SQL后缀是什么,进行动态拼接就可以了。

    欢迎留言,有时间也搞个开源项目大家玩玩。

    展开全文
  • 如题?这么设计是出于什么样的考虑?...这么设计是出于什么样的考虑?DRY 原则。就相当于我们进入一栋大楼,如果是单一入口的话,就需要一个门卫。2个入口,则需要2个。... 取得 query 数据 --->... 权限判断 ---> ....

    如题?这么设计是出于什么样的考虑?

    回复内容:

    如题?这么设计是出于什么样的考虑?

    DRY 原则。

    就相当于我们进入一栋大楼,如果是单一入口的话,就需要一个门卫。2个入口,则需要2个。

    对于 HTTP 请求来说,每次的请求模式都一样:分析 URL --> 取得 query 数据 ---> 取得 FORM 数据 ---> 过滤所有的输入以保证安全 ---> 权限判断 ---> ....

    其中还有很多,比如加载数据库配置,网站配置,缓存,全局函数等。

    这些通用的功能,可以放到一个 前端控制器 里面,前端控制器负责处理框架的逻辑,然后这个控制器根据用户的请求,将 业务逻辑 发送给相应的控制器。

    处理url的路由咯,不然你访问了哪个文件是被指定了的,PHP没有像Spring之类的能去配置URL路由的地方

    这个问题前段时间我也纠结了一下。

    由于自己想学习下php框架,用了smarty。而smarty在每次调用界面模板时都需要用到smarty类。

    也就是说每个php文件需要调用模板的时候都需要实例化smarty类,反复实例化我觉得有些无用功了,就想到用一个文件做入口,每次从这个入口进去做完所有的初始化工作,再根据地址所带参数来分配模板会更简单点。

    单入口可以把所有配置,初始化的程序统一完成。这是我目前所发现的单入口的优点。

    可以 phar 单文件上线

    本文原创发布php中文网,转载请注明出处,感谢您的尊重!

    展开全文
  • 在Android系统不断的升级过程中,Android应用的开发也有不同的变化,对于权限,Android6.0以上的系统中,引入了运行时权限检查,运行时权限分为正常权限和危险权限,当我们的App调用了需要危险权限的api时,需要向...

    前言:

    在Android系统不断的升级过程中,Android应用的开发也有不同的变化,对于权限,Android6.0以上的系统中,引入了运行时权限检查,运行时权限分为正常权限和危险权限,当我们的App调用了需要危险权限的api时,需要向系统申请权限,系统会弹出一个对话框让用户感知,只有当用户授权以后,App才能正常调用api。
    目前所有的权限类别可参考https://developer.android.google.cn/reference/android/Manifest.permission?hl=zh-cn
    如果您确定您的应用必须访问受限数据或执行受限操作才能实现某个用例,请声明相应的权限。有些权限是用户安装应用时自动授予的权限,称为安装时权限。其他权限则需要应用在运行时进一步请求权限,此类权限称为运行时权限。
    在这里插入图片描述
    图 1. 在 Android 中使用权限的概要工作流示意图。

    权限分类

    • 安装时权限
      在这里插入图片描述
      图 2. 某应用商店中显示的某个应用的安装时权限列表。
      图3显示了一个弹出式对话框,其中包含 2 个选项:允许和拒绝。

    安装时权限授予应用对受限数据的受限访问权限,并允许应用执行对系统或其他应用只有最低影响的受限操作。如果您在应用中声明了安装时权限,系统会在用户安装您的应用时自动授予应用相应权限。应用商店会在用户查看应用详情页面时向其显示安装时权限通知,如图 2 所示。

    Android 提供多个安装时权限子类型,包括普通权限和签名权限。

    a. 普通权限

    此类权限允许访问超出应用沙盒的数据和执行超出应用沙盒的操作。但是,这些数据和操作对用户隐私及对其他应用的操作带来的风险非常小。

    系统会为普通权限分配“normal”保护级别,如权限 API 参考文档页面中所示。

    b. 签名权限

    当应用声明了其他应用已定义的签名权限时,如果两个应用使用同一证书进行签名,系统会在安装时向前者授予该权限。否则,系统无法向前者授予该权限。

    • 运行时权限

    一个弹出式对话框,其中包含 2 个选项:允许和拒绝。
    运行时权限也称为危险权限,此类权限授予应用对受限数据的额外访问权限,并允许应用执行对系统和其他应用具有更严重影响的受限操作。因此,您需要先在应用中请求运行时权限,然后才能访问受限数据或执行受限操作。当应用请求运行时权限时,系统会显示运行时权限提示,如图 3 所示。
    在这里插入图片描述
    图 3. 当应用请求运行时权限时显示的系统权限提示。

    许多运行时权限会访问用户私有数据,这是一种特殊的受限数据,其中包含可能比较敏感的信息。例如,位置信息和联系信息就属于用户私有数据。

    系统会为运行时权限分配“dangerous”保护级别,如权限 API 参考文档页面中所示。
    本篇即主要说明的是运行时权限的申请。

    • 特殊权限

    特殊权限与特定的应用操作相对应。只有平台和原始设备制造商 (OEM) 可以定义特殊权限。此外,如果平台和 OEM 想要防止有人执行功能特别强大的操作(例如通过其他应用绘图),通常会定义特殊权限。

    系统设置中的特殊应用访问权限页面包含一组用户可切换的操作。其中的许多操作都以特殊权限的形式实现。

    每项特殊权限都有自己的实现细节。如需查看使用每项特殊权限的说明,请访问权限 API 参考文档页面。系统会为特殊权限分配“appop”保护级别。

    申请权限

    基本原则

    在运行时请求权限的基本原则如下:

    1. 当用户开始与需要相关权限的功能互动时,在具体使用情境下请求权限。 不要阻止用户使用应用。始终提供选项供用户取消与权限相关的指导界面流程。
    2. 如果用户拒绝或撤消某项功能所需的权限,请适当降级您的应用以便让用户可以继续使用您的应用(可能通过停用需要权限的功能来实现)。
    3. 不要对系统行为做任何假设。例如,假设某些权限会出现在同一个权限组中。权限组的作用只是在应用请求密切相关的多个权限时,帮助系统尽可能减少向用户显示的系统对话框数量。

    请求权限

    应用权限基于系统安全功能,最佳做法是将运行时权限与特定操作相关联,尽可能往后推迟到在应用的用例流程中请求权限。例如,如果应用允许用户向他人发送语音消息,请等到用户已导航到消息屏幕并已按下发送语音消息按钮后再请求权限。待用户按下该按钮后,应用再请求麦克风使用权限。
    注册权限
    如需声明应用可能请求的权限,请在应用的清单文件中添加相应的 元素。例如,需要访问相机的应用应在清单中添加以下代码行:

    <manifest ...>
        <uses-permission android:name="android.permission.CAMERA"/>
        <application ...>
            ...
        </application>
    </manifest>
    

    申请流程

    1. 在应用的清单文件中,声明应用可能需要请求的权限。

    2. 设计应用的用户体验,使应用中的特定操作与特定运行时权限相关联。应当让用户知道哪些操作可能会要求他们向您的应用授予访问其私人数据的权限。

    3. 等待用户调用应用中需要访问特定用户私人数据的任务或操作。届时,您的应用可以请求访问相应数据所需的运行时权限。

    4. 检查用户是否已授予应用所需的运行时权限。如果已授权,那么您的应用可以访问用户私人数据。如果没有,请继续执行下一步。 每次执行需要该权限的操作时,您都必须检查自己是否具有该权限。

    5. 检查您的应用是否应向用户显示理由,说明您的应用需要用户授予特定运行时权限的原因。如果系统确定您的应用不应显示理由,请继续直接执行下一步,无需显示界面元素。
      不过,如果系统确定您的应用应该显示一个理由,请在界面元素中向用户显示理由,明确说明您的应用试图访问哪些数据,以及应用获得运行时权限后可为用户提供哪些好处。用户确认理由后,请继续执行下一步。

    6. 请求您的应用访问用户私人数据所需的运行时权限。系统会显示运行时权限提示,例如权限概览页面上显示的提示。

    7. 检查用户的响应,他们可能会选择同意或拒绝授予运行时权限。

    8. 如果用户向您的应用授予权限,您就可以访问用户私人数据。如果用户拒绝授予该权限,请适当降低应用体验,使应用在未获得受该权限保护的信息时也能向用户提供功能。
      在这里插入图片描述
      图 4 说明了与此过程相关的工作流和决策组

    原生申请方法

    Android系统为我们Android开发提供了基础的权限申请方法,包括

    • 确定应用是否已获得权限

    使用系统方法 ContextCompat.checkSelfPermission() 并传入摇检查的权限。根据您的应用是否具有相应权限,此方法会返回 PERMISSION_GRANTED 或 PERMISSION_DENIED。

    • 说明为何需要获取权限

    如果 ContextCompat.checkSelfPermission() 方法返回 PERMISSION_DENIED,可调用shouldShowRequestPermissionRationale()。此方法在activity和fragment中直接调用。如果此方法返回 true,请向用户显示指导界面,在此界面中说明用户希望启用的功能为何需要特定权限。

    • 请求权限

    用户查看指导界面后或者 shouldShowRequestPermissionRationale() 的返回值表明您这次不需要显示指导界面后,您可以请求权限。用户会看到系统权限对话框,并可在其中选择是否向您的应用授予特定权限。
    ActivityCompat.requestPermissions(activity, permissions, requestCode);
    按照历来的做法,您可以在权限请求过程中自行管理请求代码,并将此请求代码包含在您的权限回调逻辑中。

    开源权限框架

    由于Android动态权限申请复杂,代码较多,所以出现了很多开源框架来帮助我们开发,我们可以学习开源框架的使用。

    1. EasyPermission

    为什么首先提这个库呢,其github地址为:https://github.com/googlesamples/easypermissions。
    官方的,最为致命。其代码示例demo如下所示。其实还是很多代码的,但是由于官方考虑的比较多,流程上肯定是没问题的。而且充分考虑了android support 和androidx的兼容,但可定制性没那么高了。由于原生方法较多,依赖onActivityResult和onRequestPermissionsResult,导致代码也多。

    public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks,EasyPermissions.RationaleCallbacks{
        private static final int RC_CAMERA_PERM = 123;
        private static final int RC_LOCATION_CONTACTS_PERM = 124;
    
        @AfterPermissionGranted(RC_CAMERA_PERM)
        public void cameraTask() {
            EasyPermissions.requestPermissions(
                this,
                getString(R.string.rationale_camera),
                RC_CAMERA_PERM,
                Manifest.permission.CAMERA);
        }
    
        @AfterPermissionGranted(RC_LOCATION_CONTACTS_PERM)
        public void locationAndContactsTask() {
            EasyPermissions.requestPermissions(
                this,
                getString(R.string.rationale_location_contacts),
                RC_LOCATION_CONTACTS_PERM,
                LOCATION_AND_CONTACTS);
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
        }
    
        @Override
        public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
            Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
        }
    
        @Override
        public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
            if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
                new AppSettingsDialog.Builder(this).build().show();
            }
        }
    }
    
    1. XXPermissions
      链式调用方式,且去除了原生依赖onActivityResult和onRequestPermissionsResult,减少了Activity和fragment的代码数量。github地址:https://github.com/getActivity/XXPermissions
      且其适配了各个Android版本的兼容和与版本相关权限的申请。其自称的亮点有:
    • 首款也是唯一一款适配 Android 11 的权限请求框架
    • 首款也是唯一一款适配所有 Android 版本的权限请求框架
    • 简洁易用:采用链式调用的方式,使用只需一句代码
    • 体积感人:功能在同类框架中最全的,但是体积是最小的
    • 适配极端情况:无论在多么极端恶劣的环境下申请权限,框架依然坚挺
    • 向下兼容属性:新权限在旧系统可以正常申请,框架会做自动适配,无需调用者适配
    • 自动检测错误:如果出现低级错误框架会主动抛出异常给调用者(仅在 Debug 下判断,把 Bug 扼杀在摇篮中)
      且做了表格对很多其他权限库进行了对比,以证明其优势。是否选用,各位自己判断。
      在这里插入图片描述
      使用的代码示例如下:
    XXPermissions.with(this)
            // 申请安装包权限
            //.permission(Permission.REQUEST_INSTALL_PACKAGES)
            // 申请悬浮窗权限
            //.permission(Permission.SYSTEM_ALERT_WINDOW)
            // 申请通知栏权限
            //.permission(Permission.NOTIFICATION_SERVICE)
            // 申请系统设置权限
            //.permission(Permission.WRITE_SETTINGS)
            // 申请单个权限
            .permission(Permission.RECORD_AUDIO)
            // 申请多个权限
            .permission(Permission.Group.CALENDAR)
            .request(new OnPermissionCallback() {
    
                @Override
                public void onGranted(List<String> permissions, boolean all) {
                    if (all) {
                        toast("获取录音和日历权限成功");
                    } else {
                        toast("获取部分权限成功,但部分权限未正常授予");
                    }
                }
    
                @Override
                public void onDenied(List<String> permissions, boolean never) {
                    if (never) {
                        toast("被永久拒绝授权,请手动授予录音和日历权限");
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(MainActivity.this, permissions);
                    } else {
                        toast("获取录音和日历权限失败");
                    }
                }
            });
    
    
    1. PermissionX

    github地址:https://github.com/guolindev/PermissionX
    这个库呢,首先一个让你铭记的,应该是作者,郭霖(第一行代码),是否看过他的书么。
    作为大神,其开发的开源库肯定也是值得我们使用的。
    此库也使用了链式调用,一步到位,且也去除了easypermission中对原生接口的依赖,用户只需要使用如下代码就好了, 且封装了提示用户和打开设置的接口,UI可定制,对部分新的系统权限也做了兼容,设置了直接的申请接口,可直接调用,减少了用户的对特殊危险权限的定制。

    PermissionX.init(activity)
        .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA, Manifest.permission.CALL_PHONE)
        .onExplainRequestReason { scope, deniedList ->
            scope.showRequestReasonDialog(deniedList, "Core fundamental are based on these permissions", "OK", "Cancel")
        }
        .onForwardToSettings { scope, deniedList ->
            scope.showForwardToSettingsDialog(deniedList, "You need to allow necessary permissions in Settings manually", "OK", "Cancel")
        }
        .request { allGranted, grantedList, deniedList ->
            if (allGranted) {
                Toast.makeText(this, "All permissions are granted", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this, "These permissions are denied: $deniedList", Toast.LENGTH_LONG).show()
            }
        }
    
    1. RxPermissions
      很多人用惯了RXjava和RXAndroid,对这种响应式编程情有独钟,有需求就有人提供,如果没有,那就是你成名的机会。
      github地址:https://github.com/tbruyelle/RxPermissions
      这里也附上其使用示例,对RX有需求的可以选用:
    rxPermissions
        .requestEachCombined(Manifest.permission.CAMERA,
                 Manifest.permission.READ_PHONE_STATE)
        .subscribe(permission -> { // will emit 1 Permission object
            if (permission.granted) {
               // All permissions are granted !
            } else if (permission.shouldShowRequestPermissionRationale)
               // At least one denied permission without ask never again
            } else {
               // At least one denied permission with ask never again
               // Need to go to the settings
            }
        });
    
    1. PermissionsDispatcher
      不得不说,哪都有注解处理的方式,在当今各种注解框架风行的今天,动态权限库也少不了注解方式的开源库,这种对代码的优点是更简洁了。
      github地址:https://github.com/permissions-dispatcher/PermissionsDispatcher
      但是这种注解有个缺点就是每次使用都要注解相应的弹框提示或打开系统设置的方法? 这个由于没去使用,就不多评论了,也行没我想的那样。但是不得不说是个很有特色的框架,是我们开发使用习惯中不可或缺的一类。
      代码示例如下:
    @RuntimePermissions
    class MainActivity : AppCompatActivity(), View.OnClickListener {
    
        @NeedsPermission(Manifest.permission.CAMERA)
        fun showCamera() {
            supportFragmentManager.beginTransaction()
                    .replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
                    .addToBackStack("camera")
                    .commitAllowingStateLoss()
        }
    
        @OnShowRationale(Manifest.permission.CAMERA)
        fun showRationaleForCamera(request: PermissionRequest) {
            showRationaleDialog(R.string.permission_camera_rationale, request)
        }
    
        @OnPermissionDenied(Manifest.permission.CAMERA)
        fun onCameraDenied() {
            Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show()
        }
    
        @OnNeverAskAgain(Manifest.permission.CAMERA)
        fun onCameraNeverAskAgain() {
            Toast.makeText(this, R.string.permission_camera_never_askagain, Toast.LENGTH_SHORT).show()
        }
    }
    

    其他框架就不一一列举了,很多还是很有特点的。

    Jetpack

    jetpack一统江湖。
    以前的support包,现在的androidx, jetpack包,其诞生的主要目的就是为了统一开发方式,避免市场上越来越多的各种框架。你服不服? 优势么也是显著的,但是官方只可能给你最核心的改进,对于一些附送的福利官方可能不会去干,这也是其他开源框架的优势,比如Android 11的后台权限等等需要各种条件检测。
    其实这里的不是专门的权限库,是随着应用的扩展,onActivityResult回调方法各种嵌套、耦合严重、难以维护,Android废弃了startActivityForResult和onActivityResult方法。
    如果使用新的activity和fragment的jetpack库,Activity Results API 是 Google官方推荐的Activity、Fragment获取数据的方式。

    implementation 'androidx.activity:activity:1.2.0-beta01'
    implementation 'androidx.fragment:fragment:1.3.0-beta01'
    

    这里虽然不是专门为申请权限开放的,但是也专门为申请权限提供了新的方法。
    新建一个Contract类,继承自ActivityResultContract<I,O>,其中,I是输入的类型,O是输出的类型。需要实现2个方法,createIntent和parseResult,输入类型I作为createIntent的参数,输出类型O作为parseResult方法的返回值,在下面的例子中,输入输出类型都是String:
    Google 预定义了很多Contract,把你们能想到的使用场景基本上都想到了,它们都定义在类ActivityResultContracts中,有以下这些Contract:

    request_permission.setOnClickListener {
        requestPermission.launch(permission.CAMERA)
    }
    
    request_multiple_permission.setOnClickListener {
        requestMultiplePermissions.launch(
            arrayOf(
                permission.BLUETOOTH,
                permission.READ_CONTACTS,
                permission.ACCESS_FINE_LOCATION
            )
        )
    }
    // 请求单个权限
    private val requestPermission =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
            // Do something if permission granted
            if (isGranted) toast("Permission is granted")
            else toast("Permission is denied")
        }
    
    // 请求一组权限
    private val requestMultiplePermissions =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions : Map<String, Boolean> ->
            // Do something if some permissions granted or denied
            permissions.entries.forEach {
                // Do checking here
            }                                                                             
    }
    

    同样的,没有了对onActivityResult和onRequestPermissionsResult的依赖。

    总结

    Android权限是在不断的变化的,每个Android新版本都会有新的权限出现,新的使用方式出现,总之是为了用户隐私安全考虑,故动态权限库还会不断的发展更新,后续肯定有更优秀的开源库出来,各位也可以学习现有的框架库根据自己公司的需求开发出更适合自己的动态库。
    水平有限,一起学习。

    展开全文
  • 后台系统设计——角色权限

    千次阅读 2021-02-19 19:48:53
    不论是哪种后台管理系统,“人员权限”始终是绕不开的话题。无论是移动端,PC端产品,登陆都需要一个账号。只是对于C端的产品,大多都是用户自己注册即可。 而对于后台产品而言,是需要公司内部人员去创建账号的。...

    一、前言

    不论是哪种后台管理系统,“人员权限”始终是绕不开的话题。无论是移动端,PC端产品,登陆都需要一个账号。只是对于C端的产品,大多都是用户自己注册即可。

    而对于后台产品而言,是需要公司内部人员去创建账号的。每个使用系统的用户都有一个独一无二的账号,每个账号都有自己对应的权限。

    多数情况下,除了超级管理员外,我们会对大多数的账号的权限做一些限制,以此来管理不同用户的使用权限问题。

    譬如,做企业使用类软件,不同部门、不同职位的人的权限是不同的;再例如一款收费产品的收费用户和免费用户权限也是迥然不同的。

    如果每个用户都单独做权限控制的话,当系统用户体量非常大的时候,就会发现以下问题:

    很多账号权限都是一样的,但每次都要再配一次;

    当某类权限用户的权限需要修改时,无法批量修改,只能一个个去修改非常耗时;

    二、经典模型——RBAC

    这时候,聪明的产品先人就创建了“角色”的概念,通过对权限集的抽象,创立了角色,通过修改角色的权限,来控制拥有该角色的人员账号的权限。

    1、RBAC——基于角色的访问控制(Role-Based Access Control )

    其基本思想是,对系统操作的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。

    这样做的好处是,不必在每次创建用户时都进行分配权限的操作,只要分配用户相应的角色即可,而且角色的权限变更比用户的权限变更要少得多,这样将简化用户的权限管理,减少系统的开销。

    按照百度百科对RBAC的定义,我们可以理解为此模型是通过角色关联用户,角色关联权限的方式,间接赋予用户权限。

    2、分类

    RBAC 模型分为RBAC0、RBAC1、RBAC2、RBAC3

    RBAC0:是RBAC的核心思想。完全支持RBAC概念的任何系统的最低需求。

    RBAC1:是把RBAC的角色分层模型。增加了角色分级的概念,一个角色可以从另一个角色继承许可权。

    RBAC2:增加了RBAC的约束模型。增加了一些限制,强调在RBAC的不同组件中在配置方面的一些限制。

    RBAC3:其实是RBAC2 + RBAC1。称为统一模型,它包含了RBAC1和RBAC2,利用传递性,也把RBAC0包括在内。这些模型构成了RBAC96模型族;

    下面,我以最为基础的RBAC0为例来讲下角色权限体系:

    三、RBAC0

    1.用户-角色-权限之间的关系

    通过上面的分析,我们已经知道,在这个模型里,涉及到3个专有名词,那就是用户、角色、权限,下面是我对这3个词的简单定义:

    用户:使用系统的人;

    角色:权限的的集合;

    权限:数据权限、功能权限(页面权限+操作权限);

    在这个RBAC0模型中,我们把权限赋予角色,再把用户关联角色来继承角色所对应的权限。用户和角色,角色和权限都是多对多的关系。用户拥有的权限等于他所有的角色持有权限的并集;

     

     

    接下来我们一一来剖析,如何把这3个名词巧妙的联合,来打造一个完整的系统用户权限管理。

    2.用户管理

     

     

    新增用户有2个关键点,第一是需要关联角色,第二是关联组织部门

    关联角色:我们通过RBAC0模型的关系图1已经知道,用户与角色之间是多对多的关系,所以如图2中的用户“吴京”,关联了战狼、伪装者的角色,那么他就拥有战狼、伪装者这2个角色权限的并集。

    用户权限亦可单独修改,修改用户的权限不影响角色本身的权限。如修改角色权限会修改角色下关联的所有用户的对应权限。

    关联组织部门:什么是组织部门呢?且看下回分解——权限管理;

    2.权限管理

    权限可以分为数据权限、功能权限两大类:

    数据权限

    顾名思义,就是账号能查看哪些数据,例如当一个公司存在多个独立的运营中心时,如何保证每个运营中心信息的独立性,如何实现运营中心之间相互不能查看业务数据,这个就涉及到数据权限。

    数据权限一般通过数据权限树来控制,那什么是数据权限树呢?

    数据权限树在一定程度上等于公司的组织结构,当然我们可以根据公司的特性去修改,并不一定要严格按照公司的部门结构来建立,只要能让此结构更为方便的为公司服务即可,如下图

     

    例如:当一个公司旗下有3个子公司,那么每个子公司都是一个独立的业务部门,这样,在给每个子公司的用户配置权限时,只需要给他配置其子公司下的数据即可;

    当业务单据需要跨公司的时候,可能需要做些特殊的处理,比如建单的时候,在选择公司时,权限放开,因为并不能确定哪些公司之间会有合作。

    查询页面的显示原则:凡涉及本公司业务的单据,拥有该公司业务数据权限的人皆可以查看。以电商中常见的仓库调拨单为例:

     

    此单据可以查看的人员有:

    A公司拥有业务组1权限的人员+B公司有B仓权限的业务组的所有人员。有点拗口哈,但不妨碍我们把事儿说清楚。

    功能权限

    功能权限是页面权限+操作权限的集合。页面权限是指你的系统分为哪些个页面,比如说销售单查询页、商品库存页等等。操作权限是指页面上能看到的:查询、新增、删除、导出等等操作。

    页面权限所有系统都是由一个个的页面组成,用户是否能看到这个页面的菜单、是否能进入这个页面就称为页面权限。

    操作权限:用户凡是在操作系统中在任何页面做的任何动作,都是操作权限,如增、删、改、查、导出、审核等等。

     

    以后台系统功能权限为例,如图4,一般来说,功能权限的配置方式都是以模块+页面名称+页面对应的操作为模型进行配置的,这样配置既清晰,出错的概率也比较小。

    3.角色管理

    角色管理是RBAC0模型的关键,以下是角色管理的图文说明:角色的建立主要包括3个模块,基础信息功能权限、数据权限。

    其中基础信息和功能权限为必填,数据权限可选填。数据权限一般在用户的账号上再进行配置。

    如果角色适用于所有的组织机构那么就可以配上数据权限,如角色是针对于某一个组织机构建立的,那配置数据权限反而是累赘。

    例如:以图3的公司结构为例,如果每个子公司都有自己的财务,并且最后需要汇总到总公司的财务体系下,这时系统如果只建立1个财务角色,那此时,就只需要配置功能权限,数据权限在新增用户的时候对总公司的财务、分公司的财务配置不同的数据权限即可;

    如果系统如果分别建立2个及以上个财务角色,1个叫总公司财务,一个叫子公司1财务、子公司1财务,那么每个财务角色就可以在新建的时候把数据权限、功能权限都配置好,新建用户的时候就无需再去配置。

    具体角色应该怎么新建,各公司可根据自身的实际情况进行灵活配置。

     

    四、总结

    RBAC0模型基本可以满足任何一个系统去建立一套相对完整的权限体系,当然它也存在着一些不足,比如:

    一个用户拥有多个角色,多角色之间如果存在互斥关系如何处理?

    当角色存在层级关系时如何给角色建立层级关系?

    ......

    这时候我们就需要引入以下这些升级模型:

    1、RBAC1:是把RBAC的角色分层模型。增加了角色分级的概念,一个角色可以从另一个角色继承权限。

     

    2、RBAC2:增加了RBAC的约束模型。添加了责任分离关系,规定了权限被赋予角色时,或角色被赋予用户时,以及当用户在某一时刻激活一个角色时所应遵循的强制性规则。

    互斥角色: 同一用户只能分配到一组互斥角色集合中至多一个角色,支持责任分离的原则。互斥角色是指各自权限互相制约的两个角色。比如财务部有会计和审核员两个角色,他们是互斥角色,那么用户不能同时拥有这两个角色,体现了职责分离原则

    基数约束: 一个角色被分配的用户数量受限;一个用户可拥有的角色数目受限;同样一个角色对应的访问权限数目也应受限,以控制高级权限在系统中的分配

    先决条件角色: 即用户想获得某上级角色,必须先获得其下一级的角色

    3、RBAC3:其实是RBAC2 + RBAC1。称为统一模型,它包含了RBAC1和RBAC2,利用传递性,也把RBAC0包括在内。

    以上是我根据自己主导过,使用过的系统,得出的对角色权限系统的归纳和总结,有不足之处,希望大家多多交流。


    链接:https://www.jianshu.com/p/29c2d7721924

    展开全文
  • RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,...
  • 本文主要想对前端权限管理功能实现做一个分享,所以并不会对后台管理的框架结构做太详细介绍,如果有朋友对其他有兴趣可以留言。基本设计和分析前端 vue + elementui服务端: node + mysql + nginx主要功能打开思否...
  • mysql权限浅谈

    2021-01-19 14:56:04
    转发:https://www.cnblogs.com/yunfeioliver/p/7887676.htmlgrant 权限 on 数据库对象 to 用户一、grant 普通数据用户,查询、插入、更新、删除 数据库中所有表数据的权利。grant select on testdb.* to common_...
  • RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,...
  • 作者:小麻雀链接:...简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系。(如...
  • RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,...
  • PHP RBAC权限管理

    2021-03-22 21:08:09
    一、基本概念RBAC(Role-Based Access Control,基于角色的访问控制),用户通过角色与权限进行关联。一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,...
  • 在后台管理项目上经常要求权限控制到按钮级,既如果当前登录用户没有新建、编辑、删除等权限就无法看到对应的功能按钮,这种需求可以使用vue的自定义指令实现 首先针对自定义指令进行封装 在util文件夹内新建...
  • RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,...
  • java 统一异常处理

    2021-04-22 21:13:59
    result.setResultMessage("权限不足"); result.setData(null); return result; } /** * 错误应答405 * @return */ public static Result error_405(){ Result result = new Result(); result.setResultCode(405); ...
  • 一、案例背景:如果你的华为云账号下有很多资源,不同资源需要对应职责的工程师进行管理,并且希望他们之间的权限彼此隔离,那么可以使用IAM功能进行权限的管理。二、实现步骤2.1登录IAM首先我们需要登录IAM控制台,...
  • 最近正在为下一项目版本设计权限管理的。看到了这篇文章,可以参考参考!RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有...
  • Linux与Windows最大的不同之一就是权限管理,如果接触过一点Linux的就会知道,Linux下的文件系统的权限相关设置非常值复杂,一旦设置错了就会导致应用运行不了,所以这篇笔记会说明Linux下的权限管理相关的初级内容...
  • 使用网关还有一个好处是屏蔽了系统内部的结构,有一个统一对外提供服务的出口。这样我们在内部进行单体拆分时,外部是无感知的。网关知道怎么路由到单体,什么时候路由到微服务。 使用API gateway的具体处理方法: ...
  • 如接口要返回用户权限异常,我们加一个状态码为101吧,下一次又要加一个数据参数异常,就加一个102的状态码。这样虽然能够照常满足业务,但状态码太凌乱了 我们应该可以参考HTTP请求返回的状态码 :下面是常见的...
  • 可以理解为一定数量的权限的集合,权限的载体。例如:一个论坛系统,“超级管理员”、“版主”都是角色。版主可管理版内的帖子、可管理版内的用户等,这些是权限。要给某个用户授予这些权限,不需要直接将权限授予...
  • RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中...
  • Android权限之shareUserId

    2021-06-05 12:28:10
    关于shareUserId每一个APK在安装到设备上的时候,设备都会为其分配一个单独的空间,mainfest中的userid就是对应一个Linux用户都会被分配到一个属于自己的统一的Linux用户ID,并且为他创建一个沙箱,以防止影响其他...
  • 最近正在为下一项目版本设计权限管理的。看到了这篇文章,可以参考参考!RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有...
  • 03 linux用户权限和软件安装与管理

    千次阅读 2021-12-06 22:11:04
    linux用户权限和软件安装与管理
  • 这就是文档型NoSql的另一大作用了,我们可以把分表之后的数据统一打在文档型NoSql中,利用文档型NoSql的搜索与聚合能力完成对全量数据的查询。 至于为什么把它放在KV型NoSql后面作为第二个写呢,因为通常搜索型NoSql...
  • superset登录(数据分析同学使用)需验证公司sso账号,且superset端所有同学共用一个presto数据源连接,需单独设计权限认证方式。 开发事件监听器,用于用户SQL查询情况审计等。 一、账号密码
  • 去年12月,欧易OKEx喊出了「重新定义交易」的口号,表示将推出统一账户。几个月过去,统一账户功能一直犹抱琵琶半遮面,没有全面开放,只是随机抽取部分用户进行了灰度测试。 3月25日,欧易OKEx宣布统一账户正式...
  • RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 51,607
精华内容 20,642
关键字:

统一权限的好处