ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零搭建工业控制系统(十):权限管理——不是所有按钮都能点

从零搭建工业控制系统(十):权限管理——不是所有按钮都能点 权限管理不是所有按钮都能点这是「从零搭建工业控制系统」系列第10篇。上篇聊完报警系统这篇说权限——谁能让设备动起来谁只能看着。一场事故引出的权限设计去年现场出过一次事故。夜班操作员想调加热器温度误触了原始IO调试面板直接写了一个0到温度寄存器。加热器瞬间断电正在跑的工艺晶圆报废。事后复盘问题不在于操作员手滑而在于系统不该让操作员看到那个面板。从那以后我做了权限系统。核心原则就一条界面只展示你有权操作的东西没权限的按钮直接不显示。三级角色模型项目里定义了三个角色权限逐级递增publicenumUserRole{Operator0,// 操作员只能跑工艺、看日志Engineer1,// 工程师能调参数、手动控制、编辑配方Admin2// 管理员能调试原始IO、管理用户}角色之间是包含关系。Engineer拥有Operator的全部权限再加自己的Admin拥有Engineer的全部再加自己的。这样设计的好处是权限只增不减不用每次都从头定义。权限映射表PermissionService是权限系统的核心。它维护了一张角色到权限的映射表publicclassPermissionService:ObservableObject{privatereadonlyDictionaryUserRole,HashSetstring_rolePermissions;privateUserRole_currentRoleUserRole.Operator;publicPermissionService(){_rolePermissionsBuildRolePermissions();}privatestaticDictionaryUserRole,HashSetstringBuildRolePermissions(){// Operator仅工艺执行 配方查看 日志查看varoperatorPermsnewHashSetstring{UserPermission.AutoView,UserPermission.AutoRunSequence,UserPermission.AutoLoadUnload,UserPermission.AutoCoverControl,UserPermission.RecipeView,UserPermission.LogView};// EngineerOperator 系统设置 手动控制 配方编辑varengineerPermsnewHashSetstring(operatorPerms){UserPermission.SettingsAccess,UserPermission.SettingsTraceView,UserPermission.SettingsIOView,UserPermission.SettingsHeater,UserPermission.ManualAccess,UserPermission.ManualMfcControl,UserPermission.ManualValveControl,UserPermission.RecipeEdit,UserPermission.RecipeCreate,UserPermission.LogExport};// AdminEngineer 原始IO调试 命令测试 用户管理varadminPermsnewHashSetstring(engineerPerms){UserPermission.SettingsRawIO,UserPermission.SettingsCommandTest,UserPermission.SettingsCommandDebug,UserPermission.AdminUserManagement};returnnewDictionaryUserRole,HashSetstring{{UserRole.Operator,operatorPerms},{UserRole.Engineer,engineerPerms},{UserRole.Admin,adminPerms}};}}权限用字符串常量定义在UserPermission类里。每个权限对应一个具体功能模块比如ManualValveControl是手动阀门控制SettingsRawIO是原始IO调试面板。可绑定属性XAML直接用PermissionService继承自ObservableObject角色变化时自动通知UI。几个便捷属性直接在XAML里绑定publicboolIsOperatorCurrentRoleUserRole.Operator;publicboolIsEngineerOrAboveCurrentRoleUserRole.Engineer;publicboolIsAdminCurrentRoleUserRole.Admin;publicstringUserDisplayText${CurrentUsername}({CurrentRole});角色切换时触发属性更新publicUserRoleCurrentRole{get_currentRole;set{if(SetProperty(ref_currentRole,value)){OnPropertyChanged(nameof(IsOperator));OnPropertyChanged(nameof(IsEngineerOrAbove));OnPropertyChanged(nameof(IsAdmin));OnPropertyChanged(nameof(UserDisplayText));_logger.Info($当前角色变更为:{value});}}}XAML里的权限控制界面元素根据角色显隐不需要在code-behind里写if-else!-- 操作员可见工艺执行面板 --StackPanelVisibility{Binding PermissionService.IsOperator, Converter{StaticResource BoolToVisibilityConverter}}ButtonContent启动SequenceCommand{Binding StartSequenceCommand}//StackPanel!-- 工程师及以上可见手动控制面板 --StackPanelVisibility{Binding PermissionService.IsEngineerOrAbove, Converter{StaticResource BoolToVisibilityConverter}}ButtonContent手动开阀门Command{Binding ManualValveCommand}//StackPanel!-- 仅管理员可见原始IO调试 --StackPanelVisibility{Binding PermissionService.IsAdmin, Converter{StaticResource BoolToVisibilityConverter}}ButtonContent原始IO写入Command{Binding RawIOWriteCommand}//StackPanel为什么用Visibility而不是IsEnabled因为禁用的按钮虽然不能点但操作员能看到有这个功能。看不到比看得到点不了更安全——你不知道的东西不会想去碰。登录流程权限的起点是登录。IUserAuthService定义了认证接口publicinterfaceIUserAuthService{UserAccount?CurrentUser{get;}TaskAuthResultLoginAsync(stringuserName,stringpassword);}登录成功后PermissionService的角色和用户名被更新// 登录成功后_permissionService.CurrentUsernameuser.UserName;_permissionService.CurrentRole(UserRole)user.Role;角色一变所有绑定了IsOperator、IsEngineerOrAbove、IsAdmin的UI元素自动更新显隐。不需要手动刷新。DI注册PermissionService注册为单例因为整个应用生命周期只有一个当前用户角色containerRegistry.RegisterSingletonIUserAuthService,UserAuthService();containerRegistry.RegisterSingletonPermissionService();ViewModel通过构造函数注入publicMainWindowViewModel(IDeviceCmdServicedeviceCmdService,IRegionManagerregionManager,PermissionServicepermissionService,ExecutionProgressServiceexecutionProgress){_permissionServicepermissionService;// ...}混淆保护权限服务的属性名在XAML里被直接引用混淆器不能重命名[System.Reflection.Obfuscation(Excludetrue,ApplyToMemberstrue)]publicclassPermissionService:ObservableObject这个注解确保Release模式下混淆后IsEngineerOrAbove这个属性名不变。不然XAML绑定路径找不到属性界面全白了。权限踩坑清单坑现象解决用IsEnabled不用Visibility操作员看到禁用按钮想方设法去点直接不显示权限检查只在UI层绕过UI直接调服务层服务层也要检查HasPermission角色用字符串大小写写错权限失效用枚举UserRole混淆后属性名变了Release版绑定失效Obfuscation排除登录后不刷新权限切换账号界面没变ObservableObject自动通知本篇小结知识点关键做法三级角色Operator/Engineer/Admin权限逐级递增权限映射DictionaryUserRole, HashSetUI控制Visibility绑定 BoolToVisibilityConverter角色属性IsOperator/IsEngineerOrAbove/IsAdmin 便捷属性单例服务PermissionService注册为Singleton混淆保护Obfuscation(Excludetrue) 保护绑定路径权限系统的核心不是能不能点而是看不看得到。看不到的按钮不会被误触。下期预告第11篇阀门控制系统实战权限管好了接下来看怎么安全地控制阀门——预检查、联锁、组合命令、状态等待。
返回列表