diff --git a/src/Admin/ThingsGateway.Admin.Application/Locales/en-US.json b/src/Admin/ThingsGateway.Admin.Application/Locales/en-US.json
index 1a700b77a..14abe94db 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Locales/en-US.json
+++ b/src/Admin/ThingsGateway.Admin.Application/Locales/en-US.json
@@ -1,4 +1,7 @@
{
+ "ThingsGateway.Admin.Application.BlazorAuthenticationHandler": {
+ "UserExpire": "User expired, please login again"
+ },
"ThingsGateway.Admin.Application.SysUser": {
"Disable": "Disable",
"Enable": "Enable",
diff --git a/src/Admin/ThingsGateway.Admin.Application/Locales/zh-CN.json b/src/Admin/ThingsGateway.Admin.Application/Locales/zh-CN.json
index 9bb6ef174..e1ed0f899 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Locales/zh-CN.json
+++ b/src/Admin/ThingsGateway.Admin.Application/Locales/zh-CN.json
@@ -1,466 +1,470 @@
{
- "ThingsGateway.Admin.Application.SysUser": {
- "Disable": "禁用",
- "Enable": "启用",
- "GrantRole": "分配角色",
- "ExitVerificat": "您已被强制下线",
- "PasswordEdited": "密码被修改,已退出登录",
- "Avatar": "头像",
- "Account": "账号",
- "Account.Required": " {0} 是必填项",
- "Password": "密码",
- "Status": "状态",
- "Phone": "手机",
- "Email": "邮箱",
- "LastLoginIp": "上次登录ip",
- "LastLoginDevice": "上次登录设备",
- "LastLoginTime": "上次登录时间",
- "LastLoginAddress": "上次登录地点",
- "LatestLoginIp": "最新登录ip",
- "LatestLoginTime": "最新登录时间",
- "LatestLoginDevice": "最新登录设备",
- "LatestLoginAddress": "最新登录地点",
- "SortCode": "排序",
- "CreateTime": "创建时间",
- "UpdateTime": "更新时间",
- "OrgNames": "机构",
- "PositionName": "职位",
- "OrgId": "机构",
- "PositionId": "职位",
- "DirectorId": "主管",
- "CheckSelf": "禁止 {0} 自己",
- "CanotDeleteAdminUser": "不可删除系统内置超管用户",
- "CanotEditAdminUser": "不可编辑超管用户",
- "CanotGrantAdmin": "不能分配超管角色",
- "EmailDup": "存在重复的邮箱 {0}",
- "AccountDup": "存在重复的账号 {0}",
- "CanotDeleteSelf": "不可删除自己",
- "EmailError": "邮箱 {0} 格式错误",
- "PhoneError": "手机号码 {0} 格式错误",
- "NoOrg": "组织机构不存在",
- "DirectorSelf": "不能设置自己为主管",
+ "ThingsGateway.Admin.Application.BlazorAuthenticationHandler": {
+ "UserExpire": "用户登录已过期,请重新登录"
+ },
+
+ "ThingsGateway.Admin.Application.SysUser": {
+ "Disable": "禁用",
+ "Enable": "启用",
+ "GrantRole": "分配角色",
+ "ExitVerificat": "您已被强制下线",
+ "PasswordEdited": "密码被修改,已退出登录",
+ "Avatar": "头像",
+ "Account": "账号",
+ "Account.Required": " {0} 是必填项",
+ "Password": "密码",
+ "Status": "状态",
+ "Phone": "手机",
+ "Email": "邮箱",
+ "LastLoginIp": "上次登录ip",
+ "LastLoginDevice": "上次登录设备",
+ "LastLoginTime": "上次登录时间",
+ "LastLoginAddress": "上次登录地点",
+ "LatestLoginIp": "最新登录ip",
+ "LatestLoginTime": "最新登录时间",
+ "LatestLoginDevice": "最新登录设备",
+ "LatestLoginAddress": "最新登录地点",
+ "SortCode": "排序",
+ "CreateTime": "创建时间",
+ "UpdateTime": "更新时间",
+ "OrgNames": "机构",
+ "PositionName": "职位",
+ "OrgId": "机构",
+ "PositionId": "职位",
+ "DirectorId": "主管",
+ "CheckSelf": "禁止 {0} 自己",
+ "CanotDeleteAdminUser": "不可删除系统内置超管用户",
+ "CanotEditAdminUser": "不可编辑超管用户",
+ "CanotGrantAdmin": "不能分配超管角色",
+ "EmailDup": "存在重复的邮箱 {0}",
+ "AccountDup": "存在重复的账号 {0}",
+ "CanotDeleteSelf": "不可删除自己",
+ "EmailError": "邮箱 {0} 格式错误",
+ "PhoneError": "手机号码 {0} 格式错误",
+ "NoOrg": "组织机构不存在",
+ "DirectorSelf": "不能设置自己为主管",
- "DemoCanotUpdatePassword": "DEMO环境不允许修改密码",
- "OldPasswordError": "原密码错误",
- "ConfirmPasswordDiff": "两次输入的密码不一致",
- "PasswordLengthLess": "密码长度不能小于 {0} ",
- "PasswordMustNum ": "密码必须包含数字",
- "PasswordMustLow": "密码必须包含小写字母",
- "PasswordMustUpp": "密码必须包含大写字母",
- "PasswordMustSpecial": "密码必须包含特殊字符"
- },
+ "DemoCanotUpdatePassword": "DEMO环境不允许修改密码",
+ "OldPasswordError": "原密码错误",
+ "ConfirmPasswordDiff": "两次输入的密码不一致",
+ "PasswordLengthLess": "密码长度不能小于 {0} ",
+ "PasswordMustNum ": "密码必须包含数字",
+ "PasswordMustLow": "密码必须包含小写字母",
+ "PasswordMustUpp": "密码必须包含大写字母",
+ "PasswordMustSpecial": "密码必须包含特殊字符"
+ },
- "ThingsGateway.Admin.Application.SysRole": {
- "Code": "编码",
- "Name": "名称",
- "Name.Required": " {0} 是必填项",
- "Category": "分类",
- "SortCode": "排序",
- "Global": "全局",
- "Status": "状态",
- "OrgId": "机构",
- "CreateTime": "创建时间",
- "UpdateTime": "更新时间",
+ "ThingsGateway.Admin.Application.SysRole": {
+ "Code": "编码",
+ "Name": "名称",
+ "Name.Required": " {0} 是必填项",
+ "Category": "分类",
+ "SortCode": "排序",
+ "Global": "全局",
+ "Status": "状态",
+ "OrgId": "机构",
+ "CreateTime": "创建时间",
+ "UpdateTime": "更新时间",
- "CanotDeleteAdmin": "不可删除系统内置超管角色",
- "CanotEditAdmin": "不可编辑超管角色",
- "CanotGrantAdmin": "不能分配超管角色",
+ "CanotDeleteAdmin": "不可删除系统内置超管角色",
+ "CanotEditAdmin": "不可编辑超管角色",
+ "CanotGrantAdmin": "不能分配超管角色",
- "NameDup": "存在重复的角色名称 {0}",
- "OrgNotNull": "机构不能为空",
- "SameOrgNameDup": "存在重复的角色名称 {0}",
- "CannotRoleScopeAll": "机构角色不能选择全局数据范围",
- "CodeDup": "存在重复的编码 {0}"
- },
- "ThingsGateway.Admin.Application.RoleCategoryEnum": {
- "Global": "全局",
- "Org": "机构"
- },
- "ThingsGateway.Admin.Application.DataScopeEnum": {
- "SCOPE_SELF": "仅自己",
- "SCOPE_ALL": "全部",
- "SCOPE_ORG": "仅所属组织",
- "SCOPE_ORG_CHILD": "所属组织及以下",
- "SCOPE_ORG_DEFINE": "自定义"
- },
- "ThingsGateway.Admin.Application.DefaultDataScope": {
- "ScopeCategory": "数据范围",
- "ScopeDefineOrgIdList": "自定义列表"
- },
- "ThingsGateway.Admin.Application.SysResource": {
- "Title": "标题",
- "Module": "模块",
- "Title.Required": "{0} 是必填项",
- "Href.Required": "{0} 是必填项",
- "Icon": "图标",
- "Href": "路径",
- "Code": "编码",
- "Category": "分类",
- "Target": "跳转类型",
- "NavLinkMatch": "匹配类型",
- "SortCode": "排序",
- "ParentId": "上级菜单",
- "CreateTime": "创建时间",
- "UpdateTime": "更新时间",
- "ResourceDup": "存在重复的名称 {0}",
- "ResourceParentChoiceSelf": "父级不能选择自己",
- "ResourceParentNull": "父级不存在 {0}",
- "NotFoundResource": "系统异常,没找到该菜单",
- "ModuleIdDiff": "模块与上级菜单不一致",
- "CanotDeleteSystemResource": "不可删除系统资源 {0}",
- "ResourceMenuHrefNotNull": "菜单的路径不能为空"
- },
+ "NameDup": "存在重复的角色名称 {0}",
+ "OrgNotNull": "机构不能为空",
+ "SameOrgNameDup": "存在重复的角色名称 {0}",
+ "CannotRoleScopeAll": "机构角色不能选择全局数据范围",
+ "CodeDup": "存在重复的编码 {0}"
+ },
+ "ThingsGateway.Admin.Application.RoleCategoryEnum": {
+ "Global": "全局",
+ "Org": "机构"
+ },
+ "ThingsGateway.Admin.Application.DataScopeEnum": {
+ "SCOPE_SELF": "仅自己",
+ "SCOPE_ALL": "全部",
+ "SCOPE_ORG": "仅所属组织",
+ "SCOPE_ORG_CHILD": "所属组织及以下",
+ "SCOPE_ORG_DEFINE": "自定义"
+ },
+ "ThingsGateway.Admin.Application.DefaultDataScope": {
+ "ScopeCategory": "数据范围",
+ "ScopeDefineOrgIdList": "自定义列表"
+ },
+ "ThingsGateway.Admin.Application.SysResource": {
+ "Title": "标题",
+ "Module": "模块",
+ "Title.Required": "{0} 是必填项",
+ "Href.Required": "{0} 是必填项",
+ "Icon": "图标",
+ "Href": "路径",
+ "Code": "编码",
+ "Category": "分类",
+ "Target": "跳转类型",
+ "NavLinkMatch": "匹配类型",
+ "SortCode": "排序",
+ "ParentId": "上级菜单",
+ "CreateTime": "创建时间",
+ "UpdateTime": "更新时间",
+ "ResourceDup": "存在重复的名称 {0}",
+ "ResourceParentChoiceSelf": "父级不能选择自己",
+ "ResourceParentNull": "父级不存在 {0}",
+ "NotFoundResource": "系统异常,没找到该菜单",
+ "ModuleIdDiff": "模块与上级菜单不一致",
+ "CanotDeleteSystemResource": "不可删除系统资源 {0}",
+ "ResourceMenuHrefNotNull": "菜单的路径不能为空"
+ },
- "ThingsGateway.Admin.Application.SysOrgCopyInput": {
- "TargetId": "目标机构",
- "ContainsChild": "包含下级",
- "ContainsPosition": "包含职位"
- },
- "ThingsGateway.Admin.Application.SysPosition": {
- "Category.Required": "{0} 是必填项",
- "Name.Required": "{0} 是必填项",
- "Code.Required": "{0} 是必填项",
- "OrgId.MinValue": "{0} 是必填项",
- "Category": "分类",
- "Name": "名称",
- "Code": "代码",
- "Status": "状态",
- "OrgId": "机构",
- "Remark": "备注",
- "SortCode": "排序",
- "CreateTime": "创建时间",
- "UpdateTime": "更新时间",
- "Dup": "存在重复的岗位 分类 {0} 名称 {1}",
- "CodeDup": "存在重复的编码 {0}",
- "NameDup": "存在重复的名称 {0}",
- "CanotContainsSelf": "不可包含自己",
- "TargetNameDup": "目标节点存在重复的名称 {0}",
- "ParentChoiceSelf": "父级不能选择自己",
- "ParentNull": "父级不存在 {0}",
- "DeleteUserFirst": "请先删除职位下的用户"
+ "ThingsGateway.Admin.Application.SysOrgCopyInput": {
+ "TargetId": "目标机构",
+ "ContainsChild": "包含下级",
+ "ContainsPosition": "包含职位"
+ },
+ "ThingsGateway.Admin.Application.SysPosition": {
+ "Category.Required": "{0} 是必填项",
+ "Name.Required": "{0} 是必填项",
+ "Code.Required": "{0} 是必填项",
+ "OrgId.MinValue": "{0} 是必填项",
+ "Category": "分类",
+ "Name": "名称",
+ "Code": "代码",
+ "Status": "状态",
+ "OrgId": "机构",
+ "Remark": "备注",
+ "SortCode": "排序",
+ "CreateTime": "创建时间",
+ "UpdateTime": "更新时间",
+ "Dup": "存在重复的岗位 分类 {0} 名称 {1}",
+ "CodeDup": "存在重复的编码 {0}",
+ "NameDup": "存在重复的名称 {0}",
+ "CanotContainsSelf": "不可包含自己",
+ "TargetNameDup": "目标节点存在重复的名称 {0}",
+ "ParentChoiceSelf": "父级不能选择自己",
+ "ParentNull": "父级不存在 {0}",
+ "DeleteUserFirst": "请先删除职位下的用户"
- },
+ },
- "ThingsGateway.Admin.Application.SysOrg": {
- "Category.Required": "{0} 是必填项",
- "Name.Required": "{0} 是必填项",
- "Code.Required": "{0} 是必填项",
- "Category": "分类",
- "Name": "名称",
- "Code": "代码",
- "Status": "状态",
- "ParentId": "上级机构",
- "Names": "机构全称",
- "Remark": "备注",
- "DirectorId": "主管",
- "SortCode": "排序",
- "CreateTime": "创建时间",
- "UpdateTime": "更新时间",
- "Dup": "存在重复的机构 分类 {0} 名称 {1}",
- "CodeDup": "存在重复的编码 {0}",
- "NameDup": "存在重复的名称 {0}",
- "CanotContainsSelf": "不可包含自己",
- "TargetNameDup": "目标节点存在重复的名称 {0}",
- "ParentChoiceSelf": "父级不能选择自己",
- "ParentNull": "父级不存在 {0}",
- "DeleteUserFirst": "请先删除机构下的用户",
- "DeleteRoleFirst": "请先删除机构下的角色",
- "DeletePositionFirst": "请先删除机构下的职位",
- "RootOrg": "无法创建顶层机构"
- },
- "ThingsGateway.Admin.Application.OrgEnum": {
- "COMPANY": "公司",
- "DEPT": "部门"
- },
- "ThingsGateway.Admin.Application.PositionCategoryEnum": {
- "HIGH": "高层",
- "MIDDLE": "中层",
- "LOW": "低层"
- },
+ "ThingsGateway.Admin.Application.SysOrg": {
+ "Category.Required": "{0} 是必填项",
+ "Name.Required": "{0} 是必填项",
+ "Code.Required": "{0} 是必填项",
+ "Category": "分类",
+ "Name": "名称",
+ "Code": "代码",
+ "Status": "状态",
+ "ParentId": "上级机构",
+ "Names": "机构全称",
+ "Remark": "备注",
+ "DirectorId": "主管",
+ "SortCode": "排序",
+ "CreateTime": "创建时间",
+ "UpdateTime": "更新时间",
+ "Dup": "存在重复的机构 分类 {0} 名称 {1}",
+ "CodeDup": "存在重复的编码 {0}",
+ "NameDup": "存在重复的名称 {0}",
+ "CanotContainsSelf": "不可包含自己",
+ "TargetNameDup": "目标节点存在重复的名称 {0}",
+ "ParentChoiceSelf": "父级不能选择自己",
+ "ParentNull": "父级不存在 {0}",
+ "DeleteUserFirst": "请先删除机构下的用户",
+ "DeleteRoleFirst": "请先删除机构下的角色",
+ "DeletePositionFirst": "请先删除机构下的职位",
+ "RootOrg": "无法创建顶层机构"
+ },
+ "ThingsGateway.Admin.Application.OrgEnum": {
+ "COMPANY": "公司",
+ "DEPT": "部门"
+ },
+ "ThingsGateway.Admin.Application.PositionCategoryEnum": {
+ "HIGH": "高层",
+ "MIDDLE": "中层",
+ "LOW": "低层"
+ },
- //controller
- "ThingsGateway.Admin.Application.AuthController": {
- //auth
- "AuthController": "登录API",
- "LoginAsync": "登录",
- "LogoutAsync": "注销"
- },
- "ThingsGateway.Admin.Application.TestController": {
- //auth
- "TestController": "测试API",
- "Test": "测试"
- },
- "ThingsGateway.Admin.Application.OpenApiAuthController": {
- //auth
- "OpenApiAuthController": "登录API",
- "LoginAsync": "登录",
- "LogoutAsync": "注销"
- },
+ //controller
+ "ThingsGateway.Admin.Application.AuthController": {
+ //auth
+ "AuthController": "登录API",
+ "LoginAsync": "登录",
+ "LogoutAsync": "注销"
+ },
+ "ThingsGateway.Admin.Application.TestController": {
+ //auth
+ "TestController": "测试API",
+ "Test": "测试"
+ },
+ "ThingsGateway.Admin.Application.OpenApiAuthController": {
+ //auth
+ "OpenApiAuthController": "登录API",
+ "LoginAsync": "登录",
+ "LogoutAsync": "注销"
+ },
- "ThingsGateway.Admin.Application.FileService": {
- "FileNullError": "文件不能为空",
- "FileLengthError": "文件大小不允许超过 {0} M",
- "FileTypeError": "不支持 {0} 格式"
- },
+ "ThingsGateway.Admin.Application.FileService": {
+ "FileNullError": "文件不能为空",
+ "FileLengthError": "文件大小不允许超过 {0} M",
+ "FileTypeError": "不支持 {0} 格式"
+ },
- "ThingsGateway.Admin.Application.UnifyResultProvider": {
- "TokenOver": "登录已过期,请重新登录",
- "NoPermission": "禁止访问,没有权限"
- },
+ "ThingsGateway.Admin.Application.UnifyResultProvider": {
+ "TokenOver": "登录已过期,请重新登录",
+ "NoPermission": "禁止访问,没有权限"
+ },
- "ThingsGateway.Admin.Application.AuthService": {
- "TenantNull": "租户不存在",
- "OrgDisable": "所属公司/部门已停用,请联系管理员",
- "SingleLoginWarn": "您的账号已在别处登录",
- "UserNull": "用户 {0} 不存在",
- "PasswordError": "密码错误次数过多,请 {0} 分钟后再试",
- "AuthErrorMax": "账号密码错误,超过 {0} 次后将锁定 {1} 分钟,错误次数 {2} ",
- "UserDisable": "账号 {0} 已停用",
- "MustDesc": "密码需要DESC加密后传入",
- "UserNoModule": "该账号未分配模块,请联系管理员"
- },
+ "ThingsGateway.Admin.Application.AuthService": {
+ "TenantNull": "租户不存在",
+ "OrgDisable": "所属公司/部门已停用,请联系管理员",
+ "SingleLoginWarn": "您的账号已在别处登录",
+ "UserNull": "用户 {0} 不存在",
+ "PasswordError": "密码错误次数过多,请 {0} 分钟后再试",
+ "AuthErrorMax": "账号密码错误,超过 {0} 次后将锁定 {1} 分钟,错误次数 {2} ",
+ "UserDisable": "账号 {0} 已停用",
+ "MustDesc": "密码需要DESC加密后传入",
+ "UserNoModule": "该账号未分配模块,请联系管理员"
+ },
- "ThingsGateway.Admin.Application.HardwareInfo": {
- "Environment": "主机环境",
- "FrameworkDescription": "NET框架",
- "OsArchitecture": "系统架构",
- "UUID": "唯一编码",
- "UpdateTime": "更新时间"
- },
- "ThingsGateway.Admin.Application.HistoryHardwareInfo": {
- "DriveUsage": "磁盘使用率",
- "MemoryUsage": "内存使用率",
- "CpuUsage": "CPU使用率",
- "Temperature": "温度",
- "Battery": "电池"
- },
+ "ThingsGateway.Admin.Application.HardwareInfo": {
+ "Environment": "主机环境",
+ "FrameworkDescription": "NET框架",
+ "OsArchitecture": "系统架构",
+ "UUID": "唯一编码",
+ "UpdateTime": "更新时间"
+ },
+ "ThingsGateway.Admin.Application.HistoryHardwareInfo": {
+ "DriveUsage": "磁盘使用率",
+ "MemoryUsage": "内存使用率",
+ "CpuUsage": "CPU使用率",
+ "Temperature": "温度",
+ "Battery": "电池"
+ },
- //oper
- "ThingsGateway.Admin.Application.OperDescAttribute": {
- //dict
- "SaveDict": "修改字典",
- "DeleteDict": "删除字典",
- "EditLoginPolicy": "修改登录策略",
- "EditPasswordPolicy": "修改密码策略",
- "EditPagePolicy": "修改页面策略",
- "EditWebsitePolicy": "修改网站设置",
- //operlog
- "DeleteOperLog": "删除操作日志",
- "ExportOperLog": "导出操作日志",
+ //oper
+ "ThingsGateway.Admin.Application.OperDescAttribute": {
+ //dict
+ "SaveDict": "修改字典",
+ "DeleteDict": "删除字典",
+ "EditLoginPolicy": "修改登录策略",
+ "EditPasswordPolicy": "修改密码策略",
+ "EditPagePolicy": "修改页面策略",
+ "EditWebsitePolicy": "修改网站设置",
+ //operlog
+ "DeleteOperLog": "删除操作日志",
+ "ExportOperLog": "导出操作日志",
- //resource
- "SaveResource": "修改资源",
- "DeleteResource": "删除资源",
+ //resource
+ "SaveResource": "修改资源",
+ "DeleteResource": "删除资源",
- //role
- "SaveRole": "修改角色",
- "DeleteRole": "删除角色",
- "RoleGrantResource": "角色授权资源",
- "RoleGrantUser": "角色授权用户",
- "RoleGrantApiPermission": "角色授权OpenApi",
- "GrantApi": "API",
- "GrantUser": "用户",
- "GrantRole": "角色",
- "GrantResource": "资源",
- //user
- "SaveUser": "修改用户",
- "DeleteuSER": "删除用户",
- "ResetPassword": "重置密码",
- "UserGrantRole": "用户授权角色",
- "UserGrantResource": "用户授权资源",
- "UserGrantApiPermission": "用户授权OpenApi",
+ //role
+ "SaveRole": "修改角色",
+ "DeleteRole": "删除角色",
+ "RoleGrantResource": "角色授权资源",
+ "RoleGrantUser": "角色授权用户",
+ "RoleGrantApiPermission": "角色授权OpenApi",
+ "GrantApi": "API",
+ "GrantUser": "用户",
+ "GrantRole": "角色",
+ "GrantResource": "资源",
+ //user
+ "SaveUser": "修改用户",
+ "DeleteuSER": "删除用户",
+ "ResetPassword": "重置密码",
+ "UserGrantRole": "用户授权角色",
+ "UserGrantResource": "用户授权资源",
+ "UserGrantApiPermission": "用户授权OpenApi",
- //usercenter
- "UpdateUserInfo": "更新个人信息",
- "WorkbenchInfo": "更新个人工作台",
- "UpdatePassword": "更新个人密码",
+ //usercenter
+ "UpdateUserInfo": "更新个人信息",
+ "WorkbenchInfo": "更新个人工作台",
+ "UpdatePassword": "更新个人密码",
- //session
- "ExitVerificat": "强退令牌",
- "ExitSession": "强退会话",
+ //session
+ "ExitVerificat": "强退令牌",
+ "ExitSession": "强退会话",
- "CopyOrg": "复制机构",
- "DeleteOrg": "删除机构",
- "SaveOrg": "保存机构",
+ "CopyOrg": "复制机构",
+ "DeleteOrg": "删除机构",
+ "SaveOrg": "保存机构",
- "DeletePosition": "删除岗位",
- "SavePosition": "保存岗位",
+ "DeletePosition": "删除岗位",
+ "SavePosition": "保存岗位",
- "NoPermission": "无权限操作",
+ "NoPermission": "无权限操作",
- "CopyResource": "复制资源",
- "ChangeParentResource": "更改父节点"
- },
+ "CopyResource": "复制资源",
+ "ChangeParentResource": "更改父节点"
+ },
- //service
+ //service
- "ThingsGateway.Admin.Application.HardwareJob": {
- "GetHardwareInfoFail": "获取硬件信息出错"
- },
+ "ThingsGateway.Admin.Application.HardwareJob": {
+ "GetHardwareInfoFail": "获取硬件信息出错"
+ },
- //dto
- "ThingsGateway.Admin.Application.UserSelectorOutput": {
- "Account": "账号",
- "OrgId": "机构"
- },
- "ThingsGateway.Admin.Application.ResourceTableSearchModel": {
- "Module": "模块",
- "Href": "路径",
- "Title": "标题"
- },
- "ThingsGateway.Admin.Application.WorkbenchInfo": {
- "Razor": "主页",
- "Shortcuts": "快捷方式"
- },
- "ThingsGateway.Admin.Application.UpdatePasswordInput": {
- "Password": "密码",
- "NewPassword": "新密码",
- "ConfirmPassword": "确认密码",
- "Password.Required": " {0} 是必填项",
- "NewPassword.Required": " {0} 是必填项",
- "ConfirmPassword.Required": " {0} 是必填项"
- },
+ //dto
+ "ThingsGateway.Admin.Application.UserSelectorOutput": {
+ "Account": "账号",
+ "OrgId": "机构"
+ },
+ "ThingsGateway.Admin.Application.ResourceTableSearchModel": {
+ "Module": "模块",
+ "Href": "路径",
+ "Title": "标题"
+ },
+ "ThingsGateway.Admin.Application.WorkbenchInfo": {
+ "Razor": "主页",
+ "Shortcuts": "快捷方式"
+ },
+ "ThingsGateway.Admin.Application.UpdatePasswordInput": {
+ "Password": "密码",
+ "NewPassword": "新密码",
+ "ConfirmPassword": "确认密码",
+ "Password.Required": " {0} 是必填项",
+ "NewPassword.Required": " {0} 是必填项",
+ "ConfirmPassword.Required": " {0} 是必填项"
+ },
- "ThingsGateway.Admin.Application.VerificatInfo": {
- "Expire": "过期时间(分)",
- "Online": "在线状态",
- "VerificatRemain": "剩余有效期",
- "VerificatTimeout": "超时时间",
- "Device": "登录设备",
- "LoginIp": "登录IP",
- "LoginTime": "登录时间"
- },
+ "ThingsGateway.Admin.Application.VerificatInfo": {
+ "Expire": "过期时间(分)",
+ "Online": "在线状态",
+ "VerificatRemain": "剩余有效期",
+ "VerificatTimeout": "超时时间",
+ "Device": "登录设备",
+ "LoginIp": "登录IP",
+ "LoginTime": "登录时间"
+ },
- "ThingsGateway.Admin.Application.SessionOutput": {
- "Account": "账号",
- "Online": "在线状态",
- "LatestLoginIp": "最新登录ip",
- "LatestLoginTime": "最新登录时间",
- "VerificatCount": "令牌数量"
- },
+ "ThingsGateway.Admin.Application.SessionOutput": {
+ "Account": "账号",
+ "Online": "在线状态",
+ "LatestLoginIp": "最新登录ip",
+ "LatestLoginTime": "最新登录时间",
+ "VerificatCount": "令牌数量"
+ },
- "ThingsGateway.Admin.Application.SysDict": {
- "Category.Required": "{0} 是必填项",
- "Name.Required": "{0} 是必填项",
- "Code.Required": "{0} 是必填项",
- "Category": "分类",
- "Name": "名称",
- "Code": "代码",
- "Remark": "备注",
- "SortCode": "排序",
- "CreateTime": "创建时间",
- "UpdateTime": "更新时间",
- "DictDup": "存在重复的配置 分类 {0} 名称 {1}",
- "DemoCanotUpdateWebsitePolicy": "DEMO环境不允许修改网站设置"
- },
+ "ThingsGateway.Admin.Application.SysDict": {
+ "Category.Required": "{0} 是必填项",
+ "Name.Required": "{0} 是必填项",
+ "Code.Required": "{0} 是必填项",
+ "Category": "分类",
+ "Name": "名称",
+ "Code": "代码",
+ "Remark": "备注",
+ "SortCode": "排序",
+ "CreateTime": "创建时间",
+ "UpdateTime": "更新时间",
+ "DictDup": "存在重复的配置 分类 {0} 名称 {1}",
+ "DemoCanotUpdateWebsitePolicy": "DEMO环境不允许修改网站设置"
+ },
- "ThingsGateway.Admin.Application.SysOperateLog": {
- "ClassName": "类名",
- "ExeMessage": "具体消息",
- "MethodName": "方法名称",
- "ParamJson": "请求参数",
- "ReqMethod": "请求方式",
- "ReqUrl": "请求地址",
- "ResultJson": "返回结果",
- "Category": "日志分类",
- "ExeStatus": "执行状态",
- "Name": "日志名称",
- "OpAccount": "账号",
- "OpBrowser": "浏览器",
- "OpIp": "ip",
- "OpOs": "系统",
- "OpTime": "操作时间",
- "VerificatId": "验证Id"
+ "ThingsGateway.Admin.Application.SysOperateLog": {
+ "ClassName": "类名",
+ "ExeMessage": "具体消息",
+ "MethodName": "方法名称",
+ "ParamJson": "请求参数",
+ "ReqMethod": "请求方式",
+ "ReqUrl": "请求地址",
+ "ResultJson": "返回结果",
+ "Category": "日志分类",
+ "ExeStatus": "执行状态",
+ "Name": "日志名称",
+ "OpAccount": "账号",
+ "OpBrowser": "浏览器",
+ "OpIp": "ip",
+ "OpOs": "系统",
+ "OpTime": "操作时间",
+ "VerificatId": "验证Id"
- },
- "ThingsGateway.Admin.Application.OperateLogPageInput": {
- "SearchDate": "时间范围",
- "Account": "操作账号",
- "Category": "分类"
- },
- "ThingsGateway.Admin.Application.LoginInput": {
- "Account": "登录账号",
- "Password": "登录密码",
- "Account.Required": "{0} 是必填项",
- "Password.Required": "{0} 是必填项"
- },
- "ThingsGateway.Admin.Application.LogoutInput": {
- "VerificatId.Required": "{0} 是必填项"
- },
- "ThingsGateway.Admin.Application.AppConfig": {
- "LoginPolicy": "登录策略",
- "PasswordPolicy": "密码策略",
- "PagePolicy": "页面设置",
- "WebsitePolicy": "网站设置"
- },
- "ThingsGateway.Admin.Application.LoginPolicy": {
- "SingleOpen": "单用户登录开关",
- "ErrorLockTime": "登录错误锁定时长(分)",
- "ErrorResetTime": "登录错误次数过期时长(分)",
- "ErrorCount": "登录错误次数锁定阈值",
- "VerificatExpireTime": "登录过期时间(分)",
- "ErrorLockTime.MinValue": " {0} 值太小",
- "ErrorResetTime.MinValue": " {0} 值太小",
- "ErrorCount.MinValue": " {0} 值太小",
- "VerificatExpireTime.MinValue": " {0} 值太小"
- },
- "ThingsGateway.Admin.Application.PagePolicy": {
- "Shortcuts": "默认快捷方式",
- "Razor": "默认主页"
- },
- "ThingsGateway.Admin.Application.PasswordPolicy": {
- "DefaultPassword": "默认用户密码",
- "DefaultPassword.Required": " {0} 是必填项",
- "PasswordMinLen": "密码最小长度",
- "PasswordMinLen.MinValue": " {0} 值太小",
- "PasswordContainNum": "包含数字",
- "PasswordContainLower": "包含小写字母",
- "PasswordContainUpper": "包含大写字母",
- "PasswordContainChar": "包含特殊字符"
- },
- "ThingsGateway.Admin.Application.WebsitePolicy": {
- "WebStatus": "是否开放",
- "CloseTip": "关闭提示",
- "CloseTip.Required": " {0} 是必填项"
- },
+ },
+ "ThingsGateway.Admin.Application.OperateLogPageInput": {
+ "SearchDate": "时间范围",
+ "Account": "操作账号",
+ "Category": "分类"
+ },
+ "ThingsGateway.Admin.Application.LoginInput": {
+ "Account": "登录账号",
+ "Password": "登录密码",
+ "Account.Required": "{0} 是必填项",
+ "Password.Required": "{0} 是必填项"
+ },
+ "ThingsGateway.Admin.Application.LogoutInput": {
+ "VerificatId.Required": "{0} 是必填项"
+ },
+ "ThingsGateway.Admin.Application.AppConfig": {
+ "LoginPolicy": "登录策略",
+ "PasswordPolicy": "密码策略",
+ "PagePolicy": "页面设置",
+ "WebsitePolicy": "网站设置"
+ },
+ "ThingsGateway.Admin.Application.LoginPolicy": {
+ "SingleOpen": "单用户登录开关",
+ "ErrorLockTime": "登录错误锁定时长(分)",
+ "ErrorResetTime": "登录错误次数过期时长(分)",
+ "ErrorCount": "登录错误次数锁定阈值",
+ "VerificatExpireTime": "登录过期时间(分)",
+ "ErrorLockTime.MinValue": " {0} 值太小",
+ "ErrorResetTime.MinValue": " {0} 值太小",
+ "ErrorCount.MinValue": " {0} 值太小",
+ "VerificatExpireTime.MinValue": " {0} 值太小"
+ },
+ "ThingsGateway.Admin.Application.PagePolicy": {
+ "Shortcuts": "默认快捷方式",
+ "Razor": "默认主页"
+ },
+ "ThingsGateway.Admin.Application.PasswordPolicy": {
+ "DefaultPassword": "默认用户密码",
+ "DefaultPassword.Required": " {0} 是必填项",
+ "PasswordMinLen": "密码最小长度",
+ "PasswordMinLen.MinValue": " {0} 值太小",
+ "PasswordContainNum": "包含数字",
+ "PasswordContainLower": "包含小写字母",
+ "PasswordContainUpper": "包含大写字母",
+ "PasswordContainChar": "包含特殊字符"
+ },
+ "ThingsGateway.Admin.Application.WebsitePolicy": {
+ "WebStatus": "是否开放",
+ "CloseTip": "关闭提示",
+ "CloseTip.Required": " {0} 是必填项"
+ },
- //enum
- "ThingsGateway.Admin.Application.ResourceCategoryEnum": {
- "Module": "模块",
- "Menu": "菜单",
- "Button": "按钮"
- },
+ //enum
+ "ThingsGateway.Admin.Application.ResourceCategoryEnum": {
+ "Module": "模块",
+ "Menu": "菜单",
+ "Button": "按钮"
+ },
- "ThingsGateway.Admin.Application.TargetEnum": {
- "_self": "本窗口",
- "_blank": "新窗口",
- "_parent": "父级窗口",
- "_top": "顶级窗口"
- },
- "ThingsGateway.Admin.Application.DictTypeEnum": {
- "System": "系统配置",
- "Define": "业务配置"
- },
+ "ThingsGateway.Admin.Application.TargetEnum": {
+ "_self": "本窗口",
+ "_blank": "新窗口",
+ "_parent": "父级窗口",
+ "_top": "顶级窗口"
+ },
+ "ThingsGateway.Admin.Application.DictTypeEnum": {
+ "System": "系统配置",
+ "Define": "业务配置"
+ },
- "ThingsGateway.Admin.Application.LogCateGoryEnum": {
- "Login": "登录",
- "Logout": "注销",
- "Operate": "操作",
- "Exception": "异常"
- },
+ "ThingsGateway.Admin.Application.LogCateGoryEnum": {
+ "Login": "登录",
+ "Logout": "注销",
+ "Operate": "操作",
+ "Exception": "异常"
+ },
- "ThingsGateway.Admin.Application.LogEnum": {
- "SUCCESS": "成功",
- "FAIL": "失败"
+ "ThingsGateway.Admin.Application.LogEnum": {
+ "SUCCESS": "成功",
+ "FAIL": "失败"
+ }
}
-}
diff --git a/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorAuthenticationStateProvider.cs b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorAuthenticationHandler.cs
similarity index 67%
rename from src/Admin/ThingsGateway.Admin.Application/Provider/BlazorAuthenticationStateProvider.cs
rename to src/Admin/ThingsGateway.Admin.Application/Provider/BlazorAuthenticationHandler.cs
index 5e9560d64..689f3bce3 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorAuthenticationStateProvider.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorAuthenticationHandler.cs
@@ -21,19 +21,17 @@ using ThingsGateway.DataEncryption;
namespace ThingsGateway.Admin.Application;
///
-public class BlazorAuthenticationStateProvider : AppAuthorizeHandler
+public class BlazorAuthenticationHandler : AppAuthorizeHandler
{
private readonly ISysDictService _sysDictService;
private readonly ISysRoleService _sysRoleService;
private readonly ISysUserService _sysUserService;
- private readonly IVerificatInfoService _verificatInfoService;
- public BlazorAuthenticationStateProvider(IVerificatInfoService verificatInfoService, ISysUserService sysUserService, ISysRoleService sysRoleService, ISysDictService sysDictService)
+ public BlazorAuthenticationHandler(ISysUserService sysUserService, ISysRoleService sysRoleService, ISysDictService sysDictService)
{
_sysUserService = sysUserService;
_sysRoleService = sysRoleService;
_sysDictService = sysDictService;
- _verificatInfoService = verificatInfoService;
}
///
@@ -48,31 +46,36 @@ public class BlazorAuthenticationStateProvider : AppAuthorizeHandler
}
else
{
- if (App.HttpContext != null)
- {
- var identity = new ClaimsIdentity();
- App.HttpContext.User = new ClaimsPrincipal(identity);
- }
- Fail(context);
+ await Fail(context).ConfigureAwait(false);
}
}
else
{
- Fail(context);// 授权失败
+ await Fail(context).ConfigureAwait(false);// 授权失败
}
- static void Fail(AuthorizationHandlerContext context)
- {
- context.Fail(); // 授权失败
- DefaultHttpContext currentHttpContext = context.GetCurrentHttpContext();
- if (currentHttpContext == null)
- return;
- currentHttpContext.Response.StatusCode = 401; //返回401给授权筛选器用
- currentHttpContext.SignoutToSwagger();
- currentHttpContext.SignOutAsync();
- }
}
+ static async Task Fail(AuthorizationHandlerContext context)
+ {
+ var verificatId = UserManager.VerificatId;
+ var verificatInfo = App.GetService().GetOne(verificatId, false);
+ if (App.HttpContext != null)
+ {
+ var identity = new ClaimsIdentity();
+ App.HttpContext.User = new ClaimsPrincipal(identity);
+ }
+ context.Fail(); // 授权失败
+ if (verificatInfo != null)
+ await App.GetService().UserLoginOut(verificatInfo.ClientIds, App.CreateLocalizerByType(typeof(BlazorAuthenticationHandler))["UserExpire"]).ConfigureAwait(false);
+
+ DefaultHttpContext currentHttpContext = context.GetCurrentHttpContext();
+ if (currentHttpContext == null)
+ return;
+ currentHttpContext.Response.StatusCode = 401; //返回401给授权筛选器用
+ currentHttpContext.SignoutToSwagger();
+ await currentHttpContext.SignOutAsync().ConfigureAwait(false);
+ }
///
public override async Task PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
{
@@ -200,21 +203,7 @@ public class BlazorAuthenticationStateProvider : AppAuthorizeHandler
var expire = (await _sysDictService.GetAppConfigAsync().ConfigureAwait(false)).LoginPolicy.VerificatExpireTime;
if (currentHttpContext == null)
{
- var verificatInfo = userId != null ? _verificatInfoService.GetOne(verificatId ?? 0) : null;//获取token信息
-
- if (verificatInfo != null)
- {
- if (verificatInfo.VerificatTimeout < DateTime.Now.AddMinutes(5))
- {
- verificatInfo.VerificatTimeout = DateTime.Now.AddMinutes(30); //新的过期时间
- _verificatInfoService.Update(verificatInfo); //更新tokne信息到cache
- }
- return true;
- }
- else
- {
- return false;
- }
+ return CheckVerificat(userId, verificatId);
}
else
{
@@ -222,13 +211,13 @@ public class BlazorAuthenticationStateProvider : AppAuthorizeHandler
{
//var token = JWTEncryption.GetJwtBearerToken(currentHttpContext); //获取当前token
- var verificatInfo = userId != null ? _verificatInfoService.GetOne(verificatId ?? 0) : null;//获取token信息
+ var verificatInfo = userId != null ? VerificatInfoService.GetOne(verificatId ?? 0, false) : null;//获取token信息
if (verificatInfo != null)
{
- if (verificatInfo.VerificatTimeout < DateTime.Now.AddMinutes(5))
+ if (verificatInfo.VerificatTimeout < DateTime.Now.AddMinutes(1))
{
- verificatInfo.VerificatTimeout = DateTime.Now.AddMinutes(verificatInfo.Expire); //新的过期时间
- _verificatInfoService.Update(verificatInfo); //更新tokne信息到cache
+ verificatInfo.VerificatTimeout = verificatInfo.VerificatTimeout.AddMinutes(verificatInfo.Expire); //新的过期时间
+ VerificatInfoService.Update(verificatInfo); //更新tokne信息到cache
}
return true;
}
@@ -244,4 +233,69 @@ public class BlazorAuthenticationStateProvider : AppAuthorizeHandler
}
}
}
+ private static IVerificatInfoService _verificatInfoService;
+ private static IVerificatInfoService VerificatInfoService
+ {
+ get
+ {
+ if (_verificatInfoService == null)
+ _verificatInfoService = App.GetService();
+
+ return _verificatInfoService;
+ }
+ }
+ public static bool CheckVerificat(long? userId, long? verificatId, bool autoUpdate = true)
+ {
+ var verificatInfo = userId != null ? VerificatInfoService.GetOne(verificatId ?? 0, false) : null;//获取token信息
+
+ if (verificatInfo != null)
+ {
+ if (verificatInfo.VerificatTimeout < DateTime.Now.AddMinutes(1))
+ {
+ if (!autoUpdate && verificatInfo.VerificatTimeout < DateTime.Now)
+ return false;
+
+ if (verificatInfo.VerificatTimeout.AddMinutes(verificatInfo.Expire) < DateTime.Now)
+ {
+ return false;
+ }
+
+ if (autoUpdate)
+ {
+ verificatInfo.VerificatTimeout = verificatInfo.VerificatTimeout.AddMinutes(verificatInfo.Expire); //新的过期时间
+ VerificatInfoService.Update(verificatInfo); //更新tokne信息到cache
+
+
+ }
+
+ //无法在server中刷新cookies,单页面应用会一直保持登录状态,所以这里不需要刷新cookies,但是F5刷新后会重新登录
+
+ //if (App.HttpContext != null)
+ //{
+ // try
+ // {
+ // var authProperties = new AuthenticationProperties
+ // {
+ // IsPersistent = true,
+ // ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(30)
+ // };
+ // await App.HttpContext.SignInAsync(Assembly.GetEntryAssembly().GetName().Name, context.User, authProperties).ConfigureAwait(false);
+
+ // }
+ // catch
+ // {
+
+ // }
+ //}
+
+ }
+
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
}
diff --git a/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorHybridAuthenticationStateProvider.cs b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorHybridAuthenticationStateProvider.cs
new file mode 100644
index 000000000..55302ecf3
--- /dev/null
+++ b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorHybridAuthenticationStateProvider.cs
@@ -0,0 +1,105 @@
+//------------------------------------------------------------------------------
+// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
+// 此代码版权(除特别声明外的代码)归作者本人Diego所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议
+// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
+// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
+// 使用文档:https://thingsgateway.cn/
+// QQ群:605534569
+//------------------------------------------------------------------------------
+
+using Microsoft.AspNetCore.Components.Authorization;
+
+using System.Security.Claims;
+
+namespace ThingsGateway.Admin.Application;
+
+///
+public class BlazorHybridAuthenticationStateProvider : AuthenticationStateProvider
+{
+ private readonly IAppService _appService;
+ private CancellationTokenSource _loopCancellationTokenSource = new CancellationTokenSource();
+
+ public BlazorHybridAuthenticationStateProvider(IAppService appService)
+ {
+ _appService = appService;
+ }
+
+ private AuthenticationState AuthenticationState = new AuthenticationState(new ClaimsPrincipal());
+ public void UserChanged(ClaimsPrincipal user)
+ {
+ AuthenticationState = new AuthenticationState(user);
+ NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
+ var oldCancellationTokenSource = _loopCancellationTokenSource;
+ if (oldCancellationTokenSource is not null)
+ {
+ oldCancellationTokenSource.Cancel();
+ oldCancellationTokenSource.Dispose();
+ }
+
+ _loopCancellationTokenSource = new CancellationTokenSource();
+ if (AuthenticationState.User?.Identity?.IsAuthenticated == true)
+ _ = RevalidationLoop(_loopCancellationTokenSource.Token);
+ }
+ private async Task RevalidationLoop(CancellationToken cancellationToken)
+ {
+ try
+ {
+ if (AuthenticationState.User.Identity?.IsAuthenticated == true)
+ {
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ bool isValid = false;
+
+ try
+ {
+ await Task.Delay(30000, cancellationToken).ConfigureAwait(false);
+ isValid = await ValidateAuthenticationStateAsync(AuthenticationState, cancellationToken).ConfigureAwait(false);
+ }
+ catch (TaskCanceledException)
+ {
+ break;
+ }
+
+ if (!isValid)
+ {
+ ForceSignOut();
+ break;
+ }
+ }
+ }
+ }
+ catch
+ {
+ ForceSignOut();
+ }
+ }
+ protected virtual async Task ValidateAuthenticationStateAsync(AuthenticationState authenticationState, CancellationToken cancellationToken)
+ {
+ var userId = authenticationState.User.Claims.FirstOrDefault(it => it.Type == ClaimConst.UserId)?.Value?.ToLong();
+ var verificatId = authenticationState.User.Claims.FirstOrDefault(it => it.Type == ClaimConst.VerificatId)?.Value?.ToLong();
+ var result = BlazorAuthenticationHandler.CheckVerificat(userId, verificatId, false);
+ if (!result)
+ {
+ var verificatInfo = App.GetService().GetOne(verificatId ?? 0, false);
+ if (App.HttpContext != null)
+ {
+ var identity = new ClaimsIdentity();
+ App.HttpContext.User = new ClaimsPrincipal(identity);
+ }
+
+ if (verificatInfo != null)
+ await App.GetService().UserLoginOut(verificatInfo.ClientIds, App.CreateLocalizerByType(typeof(BlazorAuthenticationHandler))["UserExpire"]).ConfigureAwait(false);
+ }
+ return result;
+ }
+ private void ForceSignOut()
+ {
+ var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
+ UserChanged(anonymousUser);
+ }
+ public override Task GetAuthenticationStateAsync()
+ {
+ return Task.FromResult(AuthenticationState);
+ }
+}
diff --git a/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorHybridAuthorizationHandler.cs b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorHybridAuthorizationHandler.cs
new file mode 100644
index 000000000..9210128f0
--- /dev/null
+++ b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorHybridAuthorizationHandler.cs
@@ -0,0 +1,21 @@
+//------------------------------------------------------------------------------
+// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
+// 此代码版权(除特别声明外的代码)归作者本人Diego所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议
+// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
+// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
+// 使用文档:https://thingsgateway.cn/
+// QQ群:605534569
+//------------------------------------------------------------------------------
+
+namespace ThingsGateway.Admin.Application;
+
+///
+public class BlazorHybridAuthorizationHandler : BlazorAuthenticationHandler
+{
+
+ public BlazorHybridAuthorizationHandler(ISysUserService sysUserService, ISysRoleService sysRoleService, ISysDictService sysDictService) : base(sysUserService, sysRoleService, sysDictService)
+ {
+ }
+
+}
diff --git a/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorServerAuthenticationHandler.cs b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorServerAuthenticationHandler.cs
new file mode 100644
index 000000000..d26771e10
--- /dev/null
+++ b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorServerAuthenticationHandler.cs
@@ -0,0 +1,19 @@
+//------------------------------------------------------------------------------
+// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
+// 此代码版权(除特别声明外的代码)归作者本人Diego所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议
+// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
+// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
+// 使用文档:https://thingsgateway.cn/
+// QQ群:605534569
+//------------------------------------------------------------------------------
+
+namespace ThingsGateway.Admin.Application;
+
+///
+public class BlazorServerAuthenticationHandler : BlazorAuthenticationHandler
+{
+ public BlazorServerAuthenticationHandler(ISysUserService sysUserService, ISysRoleService sysRoleService, ISysDictService sysDictService) : base(sysUserService, sysRoleService, sysDictService)
+ {
+ }
+}
diff --git a/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorServerAuthenticationStateProvider.cs b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorServerAuthenticationStateProvider.cs
new file mode 100644
index 000000000..9db26d095
--- /dev/null
+++ b/src/Admin/ThingsGateway.Admin.Application/Provider/BlazorServerAuthenticationStateProvider.cs
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
+// 此代码版权(除特别声明外的代码)归作者本人Diego所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议
+// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
+// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
+// 使用文档:https://thingsgateway.cn/
+// QQ群:605534569
+//------------------------------------------------------------------------------
+
+using Microsoft.AspNetCore.Components.Authorization;
+using Microsoft.AspNetCore.Components.Server;
+using Microsoft.Extensions.Logging;
+
+using System.Security.Claims;
+
+namespace ThingsGateway.Admin.Application;
+
+///
+public class BlazorServerAuthenticationStateProvider : RevalidatingServerAuthenticationStateProvider
+{
+ private readonly IAppService _appService;
+
+ public BlazorServerAuthenticationStateProvider(ILoggerFactory loggerFactory, IAppService appService) : base(loggerFactory)
+ {
+ _appService = appService;
+ }
+
+ protected override TimeSpan RevalidationInterval => TimeSpan.FromSeconds(30);
+
+ protected override async Task ValidateAuthenticationStateAsync(AuthenticationState authenticationState, CancellationToken cancellationToken)
+ {
+ var userId = authenticationState.User.Claims.FirstOrDefault(it => it.Type == ClaimConst.UserId)?.Value?.ToLong();
+ var verificatId = authenticationState.User.Claims.FirstOrDefault(it => it.Type == ClaimConst.VerificatId)?.Value?.ToLong();
+ var result = BlazorAuthenticationHandler.CheckVerificat(userId, verificatId, false);
+ if (!result)
+ {
+ var verificatInfo = App.GetService().GetOne(verificatId ?? 0, false);
+ if (App.HttpContext != null)
+ {
+ var identity = new ClaimsIdentity();
+ App.HttpContext.User = new ClaimsPrincipal(identity);
+ }
+
+ if (verificatInfo != null)
+ await App.GetService().UserLoginOut(verificatInfo.ClientIds, App.CreateLocalizerByType(typeof(BlazorAuthenticationHandler))["UserExpire"]).ConfigureAwait(false);
+ }
+ return result;
+ }
+}
diff --git a/src/Admin/ThingsGateway.Admin.Application/Services/AppService/AppService.cs b/src/Admin/ThingsGateway.Admin.Application/Services/AppService/AppService.cs
index 184fd64ff..b62de3867 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Services/AppService/AppService.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Services/AppService/AppService.cs
@@ -58,9 +58,9 @@ public class AppService : IAppService
}
}
- public async Task LoginAsync(ClaimsIdentity identity)
+ public async Task LoginAsync(ClaimsIdentity identity, int expire)
{
- var diffTime = DateTime.MaxValue;
+ var diffTime = DateTime.Now + TimeSpan.FromMinutes(expire);
//var diffTime = DateTime.Now.AddMinutes(expire);
await App.HttpContext!.SignInAsync(Assembly.GetEntryAssembly().GetName().Name, new ClaimsPrincipal(identity), new AuthenticationProperties()
{
diff --git a/src/ThingsGateway.Photino/Services/HybridAppService.cs b/src/Admin/ThingsGateway.Admin.Application/Services/AppService/HybridAppService.cs
similarity index 70%
rename from src/ThingsGateway.Photino/Services/HybridAppService.cs
rename to src/Admin/ThingsGateway.Admin.Application/Services/AppService/HybridAppService.cs
index 0dede34c6..c7c34daae 100644
--- a/src/ThingsGateway.Photino/Services/HybridAppService.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Services/AppService/HybridAppService.cs
@@ -14,11 +14,9 @@ using Microsoft.Extensions.DependencyInjection;
using System.Net;
using System.Security.Claims;
-using ThingsGateway.Admin.Application;
-
using UAParser;
-namespace ThingsGateway.Server;
+namespace ThingsGateway.Admin.Application;
public class HybridAppService : IAppService
{
@@ -30,6 +28,18 @@ public class HybridAppService : IAppService
}
public ClientInfo? ClientInfo { get; }
+ private static BlazorHybridAuthenticationStateProvider _authenticationStateProvider;
+ private static BlazorHybridAuthenticationStateProvider AuthenticationStateProvider
+ {
+ get
+ {
+ if (_authenticationStateProvider == null)
+ _authenticationStateProvider = ((BlazorHybridAuthenticationStateProvider)App.RootServices.GetService());
+
+ return _authenticationStateProvider;
+ }
+ }
+
private ClaimsPrincipal? user;
public ClaimsPrincipal? User
@@ -37,8 +47,12 @@ public class HybridAppService : IAppService
get { return user; }
internal set
{
+ if (user == value)
+ {
+ return;
+ }
user = value;
- ((BlazorHybridAuthenticationStateProvider)App.RootServices.GetService()).UserChanged();
+ AuthenticationStateProvider.UserChanged(user);
}
}
@@ -55,9 +69,10 @@ public class HybridAppService : IAppService
return Task.CompletedTask;
}
- public Task LoginAsync(ClaimsIdentity claimsIdentity)
+ public Task LoginAsync(ClaimsIdentity claimsIdentity, int expire)
{
User = new ClaimsPrincipal(claimsIdentity);
return Task.CompletedTask;
}
+
}
diff --git a/src/Admin/ThingsGateway.Admin.Application/Services/AppService/IAppService.cs b/src/Admin/ThingsGateway.Admin.Application/Services/AppService/IAppService.cs
index 09e577a01..f3b77279a 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Services/AppService/IAppService.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Services/AppService/IAppService.cs
@@ -49,7 +49,7 @@ public interface IAppService
/// LoginAsync
///
///
- public Task LoginAsync(ClaimsIdentity claimsIdentity);
+ public Task LoginAsync(ClaimsIdentity claimsIdentity, int expire);
diff --git a/src/Admin/ThingsGateway.Admin.Application/Services/Auth/AuthService.cs b/src/Admin/ThingsGateway.Admin.Application/Services/Auth/AuthService.cs
index 37b2dda28..7798ae896 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Services/Auth/AuthService.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Services/Auth/AuthService.cs
@@ -229,7 +229,7 @@ public class AuthService : IAuthService
identity.AddClaim(new Claim(ClaimConst.OrgId, sysUser.OrgId.ToString()));
identity.AddClaim(new Claim(ClaimConst.TenantId, input.TenantId?.ToString() ?? "0"));
- await _appService.LoginAsync(identity).ConfigureAwait(false);
+ await _appService.LoginAsync(identity, expire).ConfigureAwait(false);
#endregion cookie
}
diff --git a/src/ThingsGateway.Photino/Services/HybridAuthRazorService.cs b/src/Admin/ThingsGateway.Admin.Application/Services/Auth/HybridAuthRazorService.cs
similarity index 95%
rename from src/ThingsGateway.Photino/Services/HybridAuthRazorService.cs
rename to src/Admin/ThingsGateway.Admin.Application/Services/Auth/HybridAuthRazorService.cs
index 009abc2c8..648a96c0c 100644
--- a/src/ThingsGateway.Photino/Services/HybridAuthRazorService.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Services/Auth/HybridAuthRazorService.cs
@@ -8,10 +8,9 @@
// QQ群:605534569
//------------------------------------------------------------------------------
-using ThingsGateway.Admin.Application;
using ThingsGateway.Razor;
-namespace ThingsGateway.Server;
+namespace ThingsGateway.Admin.Application;
public class HybridAuthRazorService : IAuthRazorService
diff --git a/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/IVerificatInfoService.cs b/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/IVerificatInfoService.cs
index ea1530278..1881b7f16 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/IVerificatInfoService.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/IVerificatInfoService.cs
@@ -28,7 +28,7 @@ public interface IVerificatInfoService
List? GetListByUserIds(List userIds);
- VerificatInfo GetOne(long id);
+ VerificatInfo GetOne(long id, bool delete = true);
void RemoveAllClientId();
diff --git a/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/VerificatInfoService.cs b/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/VerificatInfoService.cs
index e0a8fe090..aa09a8509 100644
--- a/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/VerificatInfoService.cs
+++ b/src/Admin/ThingsGateway.Admin.Application/Services/VerificatInfo/VerificatInfoService.cs
@@ -22,17 +22,19 @@ internal sealed class VerificatInfoService : BaseService, IVerifi
{
#region 查询
- public VerificatInfo GetOne(long id)
+ public VerificatInfo GetOne(long id, bool delete = true)
{
//先从Cache拿
var verificatInfo = App.CacheService.HashGetOne(CacheConst.Cache_Token, id.ToString());
verificatInfo ??= GetFromDb(id);
- if (verificatInfo != null)
+ if (verificatInfo != null && delete)
+ {
if (verificatInfo.VerificatTimeout.AddSeconds(30) < DateTime.Now)
{
Delete(verificatInfo.Id);
return null;
}
+ }
return verificatInfo;
}
diff --git a/src/Admin/ThingsGateway.Admin.Razor/Context/BlazorAppContext.cs b/src/Admin/ThingsGateway.Admin.Razor/Context/BlazorAppContext.cs
index f55d506e2..905a0c5c4 100644
--- a/src/Admin/ThingsGateway.Admin.Razor/Context/BlazorAppContext.cs
+++ b/src/Admin/ThingsGateway.Admin.Razor/Context/BlazorAppContext.cs
@@ -11,6 +11,7 @@
using Mapster;
using ThingsGateway.Admin.Application;
+using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Extension;
namespace ThingsGateway.Admin.Razor;
@@ -151,7 +152,7 @@ public class BlazorAppContext
CurrentUser = (await SysUserService.GetUserByIdAsync(UserManager.UserId))!;
}
}
-
+ TimeTick timeTick = new("50000");
///
/// 是否拥有按钮授权
///
@@ -160,6 +161,9 @@ public class BlazorAppContext
///
public bool IsHasButtonWithRole(string url, string code)
{
+ if (timeTick.IsTickHappen())
+ BlazorAuthenticationHandler.CheckVerificat(UserManager.UserId, UserManager.VerificatId);
+
if (UserManager.SuperAdmin)
return true;
url ??= string.Empty;
diff --git a/src/Admin/ThingsGateway.AdminServer/Program/Startup.cs b/src/Admin/ThingsGateway.AdminServer/Program/Startup.cs
index dae15885b..e67117c3c 100644
--- a/src/Admin/ThingsGateway.AdminServer/Program/Startup.cs
+++ b/src/Admin/ThingsGateway.AdminServer/Program/Startup.cs
@@ -9,6 +9,7 @@
//------------------------------------------------------------------------------
using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.StaticFiles;
@@ -296,8 +297,9 @@ public class Startup : AppStartup
#if NET8_0_OR_GREATER
services.AddCascadingAuthenticationState();
#endif
- services.AddScoped();
-
+ services.AddAuthorizationCore();
+ services.AddScoped();
+ services.AddScoped();
}
diff --git a/src/Foundation/ThingsGateway.Foundation/Common/IncrementCount.cs b/src/Admin/ThingsGateway.NewLife.X/Common/IncrementCount.cs
similarity index 98%
rename from src/Foundation/ThingsGateway.Foundation/Common/IncrementCount.cs
rename to src/Admin/ThingsGateway.NewLife.X/Common/IncrementCount.cs
index 5cc339116..95ff20c60 100644
--- a/src/Foundation/ThingsGateway.Foundation/Common/IncrementCount.cs
+++ b/src/Admin/ThingsGateway.NewLife.X/Common/IncrementCount.cs
@@ -8,7 +8,7 @@
// QQ群:605534569
//------------------------------------------------------------------------------
-namespace ThingsGateway.Foundation;
+namespace ThingsGateway.NewLife;
///
/// 自增数据类,用于自增数据,可以设置最大值,初始值,自增步长等。
diff --git a/src/Foundation/ThingsGateway.Foundation/Common/TimeTick.cs b/src/Admin/ThingsGateway.NewLife.X/Common/TimeTick.cs
similarity index 98%
rename from src/Foundation/ThingsGateway.Foundation/Common/TimeTick.cs
rename to src/Admin/ThingsGateway.NewLife.X/Common/TimeTick.cs
index 6d1b73061..66afaa85c 100644
--- a/src/Foundation/ThingsGateway.Foundation/Common/TimeTick.cs
+++ b/src/Admin/ThingsGateway.NewLife.X/Common/TimeTick.cs
@@ -1,6 +1,6 @@
using ThingsGateway.NewLife.Threading;
-namespace ThingsGateway.Foundation;
+namespace ThingsGateway.NewLife;
///
/// 最小时间间隔 10 毫秒
diff --git a/src/Foundation/ThingsGateway.Foundation/Common/WaitLock.cs b/src/Admin/ThingsGateway.NewLife.X/Common/WaitLock.cs
similarity index 91%
rename from src/Foundation/ThingsGateway.Foundation/Common/WaitLock.cs
rename to src/Admin/ThingsGateway.NewLife.X/Common/WaitLock.cs
index 73a2ab43f..0c94e85ac 100644
--- a/src/Foundation/ThingsGateway.Foundation/Common/WaitLock.cs
+++ b/src/Admin/ThingsGateway.NewLife.X/Common/WaitLock.cs
@@ -8,12 +8,12 @@
// QQ群:605534569
//------------------------------------------------------------------------------
-namespace ThingsGateway.Foundation;
+namespace ThingsGateway.NewLife;
///
/// WaitLock,使用轻量级SemaphoreSlim锁
///
-public sealed class WaitLock : DisposableObject
+public sealed class WaitLock : IDisposable
{
private readonly SemaphoreSlim _waiterLock;
@@ -40,7 +40,7 @@ public sealed class WaitLock : DisposableObject
///
~WaitLock()
{
- this.SafeDispose();
+ Dispose();
}
public bool Waited => _waiterLock.CurrentCount == 0;
@@ -89,10 +89,11 @@ public sealed class WaitLock : DisposableObject
return _waiterLock.WaitAsync(millisecondsTimeout, cancellationToken);
}
- ///
- protected override void Dispose(bool disposing)
+ bool DisposedValue;
+ public void Dispose()
{
- base.Dispose(disposing);
- _waiterLock.SafeDispose();
+ DisposedValue = true;
+ _waiterLock?.TryDispose();
+ GC.SuppressFinalize(this);
}
}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index f49fcd580..daaaa5eb0 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -1,8 +1,8 @@
- 10.0.0.21
- 10.0.0.21
+ 10.0.0.22
+ 10.0.0.22
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs b/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs
index 224a52bd4..cc1f7a73f 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs
@@ -8,6 +8,8 @@
// QQ群:605534569
//------------------------------------------------------------------------------
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs b/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs
index d80f0a441..9ed474ac6 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs
@@ -10,6 +10,8 @@
using System.IO.Ports;
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
public interface IChannelOptions
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs
index 98f52216e..4285d6186 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs
@@ -8,6 +8,8 @@
// QQ群:605534569
//------------------------------------------------------------------------------
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs
index bceea7aa3..7dea03a89 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs
@@ -10,6 +10,8 @@
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs
index 7aa04ac3a..b68ef3446 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs
@@ -10,6 +10,8 @@
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
using TouchSocket.SerialPorts;
namespace ThingsGateway.Foundation;
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs
index 05a3c23da..6789bc4d7 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs
@@ -13,6 +13,8 @@
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs
index fa932337d..1a6a6179b 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs
@@ -10,6 +10,8 @@
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs
index 659b2fd50..fad637b24 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs
@@ -11,6 +11,8 @@
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs
index 3bb6422dd..094fb7146 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs
@@ -10,6 +10,8 @@
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Variable/IVariableSource.cs b/src/Foundation/ThingsGateway.Foundation/Variable/IVariableSource.cs
index 05192e01e..d4c449b7f 100644
--- a/src/Foundation/ThingsGateway.Foundation/Variable/IVariableSource.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Variable/IVariableSource.cs
@@ -8,6 +8,8 @@
// QQ群:605534569
//------------------------------------------------------------------------------
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Variable/VariableSourceClass.cs b/src/Foundation/ThingsGateway.Foundation/Variable/VariableSourceClass.cs
index fd30d76ec..317eb1d00 100644
--- a/src/Foundation/ThingsGateway.Foundation/Variable/VariableSourceClass.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Variable/VariableSourceClass.cs
@@ -8,6 +8,8 @@
// QQ群:605534569
//------------------------------------------------------------------------------
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Foundation;
///
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Common/DoTask.cs b/src/Gateway/ThingsGateway.Gateway.Application/Common/DoTask.cs
index 3eaffd9bf..faf91d44f 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Common/DoTask.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Common/DoTask.cs
@@ -10,6 +10,8 @@
using Microsoft.Extensions.Logging;
+using ThingsGateway.NewLife;
+
using TouchSocket.Core;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalAlarmModel.cs b/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalAlarmModel.cs
index 474040c4f..4963def6d 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalAlarmModel.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalAlarmModel.cs
@@ -10,6 +10,8 @@
using Mapster;
+using ThingsGateway.NewLife;
+
using TouchSocket.Core;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalDeviceModel.cs b/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalDeviceModel.cs
index 0819e6e98..fa138e1af 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalDeviceModel.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalDeviceModel.cs
@@ -10,6 +10,8 @@
using Mapster;
+using ThingsGateway.NewLife;
+
using TouchSocket.Core;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalVariableModel.cs b/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalVariableModel.cs
index 668253552..b8e759f75 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalVariableModel.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Driver/Business/Cache/Interval/BusinessBaseWithCacheIntervalVariableModel.cs
@@ -10,6 +10,8 @@
using Mapster;
+using ThingsGateway.NewLife;
+
using TouchSocket.Core;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Driver/DriverBase.cs b/src/Gateway/ThingsGateway.Gateway.Application/Driver/DriverBase.cs
index 99987eba4..bf2f569fc 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Driver/DriverBase.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Driver/DriverBase.cs
@@ -12,6 +12,7 @@ using BootstrapBlazor.Components;
using Microsoft.Extensions.Localization;
+using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Threading;
using ThingsGateway.Razor;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Model/ChannelRuntime.cs b/src/Gateway/ThingsGateway.Gateway.Application/Model/ChannelRuntime.cs
index 628abd139..f7d2f6918 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Model/ChannelRuntime.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Model/ChannelRuntime.cs
@@ -14,6 +14,8 @@ using Mapster;
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
using TouchSocket.Core;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableMethod.cs b/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableMethod.cs
index 21caba701..f788e1ce2 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableMethod.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableMethod.cs
@@ -8,6 +8,8 @@
// QQ群:605534569
//------------------------------------------------------------------------------
+using ThingsGateway.NewLife;
+
using TouchSocket.Core;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableSourceRead.cs b/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableSourceRead.cs
index 162525e3d..c3b98eb36 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableSourceRead.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Model/VariableSourceRead.cs
@@ -8,6 +8,8 @@
// QQ群:605534569
//------------------------------------------------------------------------------
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Gateway.Application;
///
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelRuntimeService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelRuntimeService.cs
index 27fa0a3aa..bee30e4bb 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelRuntimeService.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelRuntimeService.cs
@@ -15,6 +15,7 @@ using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using ThingsGateway.Extension.Generic;
+using ThingsGateway.NewLife;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceRuntimeService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceRuntimeService.cs
index 5886ff701..b9cda8d55 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceRuntimeService.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceRuntimeService.cs
@@ -15,6 +15,7 @@ using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using ThingsGateway.Extension.Generic;
+using ThingsGateway.NewLife;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/ThingsGateway.Photino/Services/HybridGatewayExportService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayExport/HybridGatewayExportService.cs
similarity index 96%
rename from src/ThingsGateway.Photino/Services/HybridGatewayExportService.cs
rename to src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayExport/HybridGatewayExportService.cs
index 5ca56f22e..5a6b875b8 100644
--- a/src/ThingsGateway.Photino/Services/HybridGatewayExportService.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayExport/HybridGatewayExportService.cs
@@ -8,12 +8,11 @@
// QQ群:605534569
//------------------------------------------------------------------------------
-using ThingsGateway.Admin.Application;
using ThingsGateway.Gateway.Application;
namespace ThingsGateway.Server;
-internal sealed class HybridGatewayExportService : IGatewayExportService
+public sealed class HybridGatewayExportService : IGatewayExportService
{
private readonly IChannelRuntimeService _channelService;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/ChannelManage/ChannelThreadManage.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/ChannelManage/ChannelThreadManage.cs
index 74bab2b18..7604983a3 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/ChannelManage/ChannelThreadManage.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/ChannelManage/ChannelThreadManage.cs
@@ -14,6 +14,8 @@ using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
namespace ThingsGateway.Gateway.Application;
internal sealed class ChannelThreadManage : IChannelThreadManage
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/DeviceManage/DeviceThreadManage.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/DeviceManage/DeviceThreadManage.cs
index 1cfca1764..df271b265 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/DeviceManage/DeviceThreadManage.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayMonitor/DeviceManage/DeviceThreadManage.cs
@@ -15,6 +15,8 @@ using Microsoft.Extensions.Localization;
using System.Collections.Concurrent;
+using ThingsGateway.NewLife;
+
using TouchSocket.Core;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Plugin/PluginService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Plugin/PluginService.cs
index de555ac7f..df1c8558d 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Plugin/PluginService.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Plugin/PluginService.cs
@@ -21,6 +21,7 @@ using System.Reflection;
using System.Runtime.Loader;
using ThingsGateway.Extension.Generic;
+using ThingsGateway.NewLife;
using TouchSocket.Core;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableRuntimeService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableRuntimeService.cs
index 00d1a3ac3..849efda74 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableRuntimeService.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableRuntimeService.cs
@@ -15,6 +15,7 @@ using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using ThingsGateway.Extension.Generic;
+using ThingsGateway.NewLife;
namespace ThingsGateway.Gateway.Application;
diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs
index e1a552a72..0e0c25ce4 100644
--- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs
@@ -26,6 +26,7 @@ using System.Text;
using ThingsGateway.Extension.Generic;
using ThingsGateway.Foundation.Extension.Dynamic;
+using ThingsGateway.NewLife;
using TouchSocket.Core;
diff --git a/src/Gateway/ThingsGateway.Gateway.Razor/Pages/GatewayMonitorPage/ChannelDeviceTree.razor.cs b/src/Gateway/ThingsGateway.Gateway.Razor/Pages/GatewayMonitorPage/ChannelDeviceTree.razor.cs
index e83e094a9..dd320aa5c 100644
--- a/src/Gateway/ThingsGateway.Gateway.Razor/Pages/GatewayMonitorPage/ChannelDeviceTree.razor.cs
+++ b/src/Gateway/ThingsGateway.Gateway.Razor/Pages/GatewayMonitorPage/ChannelDeviceTree.razor.cs
@@ -16,6 +16,7 @@ using SqlSugar;
using ThingsGateway.Admin.Razor;
using ThingsGateway.Gateway.Application;
+using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.NewLife.Json.Extension;
@@ -939,7 +940,7 @@ public partial class ChannelDeviceTree : IDisposable
private ExecutionContext? context;
- private Foundation.WaitLock WaitLock = new();
+ private WaitLock WaitLock = new();
protected override void OnInitialized()
{
diff --git a/src/Plugin/ThingsGateway.Foundation.Modbus/Helper/PackHelper.cs b/src/Plugin/ThingsGateway.Foundation.Modbus/Helper/PackHelper.cs
index bf6b698a4..641ea7f7d 100644
--- a/src/Plugin/ThingsGateway.Foundation.Modbus/Helper/PackHelper.cs
+++ b/src/Plugin/ThingsGateway.Foundation.Modbus/Helper/PackHelper.cs
@@ -8,6 +8,7 @@
// QQ群:605534569
//------------------------------------------------------------------------------
+using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Extension;
namespace ThingsGateway.Foundation.Modbus;
diff --git a/src/Plugin/ThingsGateway.Plugin.DB/SqlDB/SqlDbProducer.other.cs b/src/Plugin/ThingsGateway.Plugin.DB/SqlDB/SqlDbProducer.other.cs
index 38c6b09b0..0b84e5f9f 100644
--- a/src/Plugin/ThingsGateway.Plugin.DB/SqlDB/SqlDbProducer.other.cs
+++ b/src/Plugin/ThingsGateway.Plugin.DB/SqlDB/SqlDbProducer.other.cs
@@ -11,6 +11,7 @@
using Mapster;
using ThingsGateway.Foundation;
+using ThingsGateway.NewLife;
using ThingsGateway.Plugin.DB;
using TouchSocket.Core;
diff --git a/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttClient/MqttClient.other.cs b/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttClient/MqttClient.other.cs
index 8d03e55ee..781b1b2f3 100644
--- a/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttClient/MqttClient.other.cs
+++ b/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttClient/MqttClient.other.cs
@@ -24,6 +24,7 @@ using System.Text;
using ThingsGateway.Extension.Generic;
using ThingsGateway.Foundation;
using ThingsGateway.Foundation.Extension.Generic;
+using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.NewLife.Json.Extension;
diff --git a/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttCollect/MqttCollect.other.cs b/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttCollect/MqttCollect.other.cs
index 859f128a7..9d8466168 100644
--- a/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttCollect/MqttCollect.other.cs
+++ b/src/Plugin/ThingsGateway.Plugin.Mqtt/MqttCollect/MqttCollect.other.cs
@@ -18,6 +18,7 @@ using System.Text;
using ThingsGateway.Foundation;
using ThingsGateway.Gateway.Application.Extensions;
+using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.NewLife.Json.Extension;
diff --git a/src/ThingsGateway.Photino/Services/BlazorHybridAuthenticationStateProvider.cs b/src/ThingsGateway.Photino/Services/BlazorHybridAuthenticationStateProvider.cs
deleted file mode 100644
index ee9675554..000000000
--- a/src/ThingsGateway.Photino/Services/BlazorHybridAuthenticationStateProvider.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-//------------------------------------------------------------------------------
-// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
-// 此代码版权(除特别声明外的代码)归作者本人Diego所有
-// 源代码使用协议遵循本仓库的开源协议及附加协议
-// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
-// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
-// 使用文档:https://thingsgateway.cn/
-// QQ群:605534569
-//------------------------------------------------------------------------------
-
-using Microsoft.AspNetCore.Components.Authorization;
-
-using System.Security.Claims;
-
-using ThingsGateway.Admin.Application;
-
-namespace ThingsGateway.Server;
-
-///
-public class BlazorHybridAuthenticationStateProvider : AuthenticationStateProvider
-{
- private readonly IAppService _appService;
-
- public BlazorHybridAuthenticationStateProvider(IAppService appService)
- {
- _appService = appService;
- }
-
- private AuthenticationState currentUser = new AuthenticationState(new ClaimsPrincipal());
- public void UserChanged()
- {
- currentUser = new AuthenticationState(_appService.User);
- NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
- }
- public override Task GetAuthenticationStateAsync()
- {
- return Task.FromResult(currentUser);
- }
-}
diff --git a/src/ThingsGateway.Photino/Services/BlazorHybridAuthorizationHandler.cs b/src/ThingsGateway.Photino/Services/BlazorHybridAuthorizationHandler.cs
deleted file mode 100644
index efecfd540..000000000
--- a/src/ThingsGateway.Photino/Services/BlazorHybridAuthorizationHandler.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-//------------------------------------------------------------------------------
-// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
-// 此代码版权(除特别声明外的代码)归作者本人Diego所有
-// 源代码使用协议遵循本仓库的开源协议及附加协议
-// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
-// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
-// 使用文档:https://thingsgateway.cn/
-// QQ群:605534569
-//------------------------------------------------------------------------------
-
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.DependencyInjection;
-
-using ThingsGateway.Admin.Application;
-
-namespace ThingsGateway.Server;
-
-///
-public class BlazorHybridAuthorizationHandler : BlazorAuthenticationStateProvider
-{
- private readonly HybridAppService _appService;
-
- public BlazorHybridAuthorizationHandler(IVerificatInfoService verificatInfoService, ISysUserService sysUserService, ISysRoleService sysRoleService, ISysDictService sysDictService) : base(verificatInfoService, sysUserService, sysRoleService, sysDictService)
- {
- _appService = App.RootServices.GetService();
- }
-
- ///
- public override Task HandleAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
- {
- _appService.User = context.User;
- return base.HandleAsync(context, httpContext);
- }
-
-}
diff --git a/src/ThingsGateway.Server/Program/Startup.cs b/src/ThingsGateway.Server/Program/Startup.cs
index 7309e463e..d9b5c3fca 100644
--- a/src/ThingsGateway.Server/Program/Startup.cs
+++ b/src/ThingsGateway.Server/Program/Startup.cs
@@ -9,6 +9,7 @@
//------------------------------------------------------------------------------
using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.StaticFiles;
@@ -291,8 +292,9 @@ public class Startup : AppStartup
#if NET8_0_OR_GREATER
services.AddCascadingAuthenticationState();
#endif
- services.AddScoped();
-
+ services.AddAuthorizationCore();
+ services.AddScoped();
+ services.AddScoped();
}
diff --git a/src/Version.props b/src/Version.props
index a5203675f..168c28b2a 100644
--- a/src/Version.props
+++ b/src/Version.props
@@ -1,6 +1,6 @@
- 10.0.0.21
+ 10.0.0.22