Authorization and Profile Application Block 1.0研究总结

 By Ben


Authorization and Profile Application Block 1.0研究报告

1.  课题简介

利用WindowsPrincipalGenericPrincipal可以实现验证授权. 但权限只能分到角色. 利用Authorization and Profile Application Block 1.0 不仅有效实现权限分配到角色, 更能分配到任务, 操作

2. 研究过程

2.1. 概述

Authorization and Profile Application Block是一个.net验证授权开发工具. 基于windows passport管理和NTLM 等实现用户验证授权.

利用AzMan实现很方便灵活地实现Authorization、可以随意定制profile内容方便开发使用、可以有多种profile数据存储介质……

运行Authorization and Profile Application Block对系统需求环境l:

1)        .NET Framework version 1.1

2)        数据存储(比如:profile数据使用Sql保存, 则需要Sql Server)

3)        Windows Server 2003 or Windows 2000 Server with Service Pack 4 (因为BlockAzManProvider需要Authorization Manager [AzMan])

三大组件:

1)                    Microsoft.ApplicationBlocks.Security.dll    Block的一些对象概念定义层

2)                    Microsoft.ApplicationBlocks.Common.dll   BlockProvider定义层

3)                   Microsoft.ApplicationBlocks.Security.Providers.dll  可以插入应用系统business层的Provider的逻辑层

安装Block

下载位置:http://www.microsoft.com/downloads/details.aspx?FamilyId=BA983AD5-E74F-4BE9-B146-9D2D2C6F8E81&displaylang=en

安装后运行 [安装位置] /Security/Database/Profile.sql 安装profile存储数据库(demo使用).

(过程略)

2.2.  研究环境

WinXP, SQL Server 2000 + SP 3A , .Net

附件:   (点击下载Demo附件)     

DemoApp项目:  win应用项目

Microsoft.Interop.Security.AzRoles.dll: Authorization Manager

Common 项目:  Auth Pro 提供

Security/Security项目: Auth Pro提供

Security/Providers项目:  Auth Pro提供的Authorization Profile的处理器

2.3. 研究思路

1. 了解熟悉asp.net 一般验证授权的所有做法

2. 认识Authorization and Profile Application Block

3. 配置Authorization and Profile Application Block开发使用环境

4. 使用Block, 设计profile解决方案demo

5. 使用Block, 设计Authorization解决方案demo

6. 总结使用Block的使用和设计思想

 

2.4.  Block设计架构


也由此可知
Authorization Profile是基本独立管理的, 管理结构也基本相同.

Configuration:

可以保存到config文件里或其他介质

数据存储:

可以是sql, xml等介质

由架构图可以看出Block主要实现或提供了什么

 

1.     Extended Principal

普通的WindowsPrincipalGenericPrincipal实现不了复杂的业务, ExtendedPrincipal继承IPrincipal基础上还自定义了:

       Bool CheckAccess 根据是否有权限

       StringCollection GetRoles 获所有角色

      

2.     Authorization Provider Interface

提供IAuthorizationProvider:

       Initialize

       StringCollection GetRoles

       Bool CheckAccess

 

3.     Profile Provider Interface

提供 IProfileProvider:
Initialize
Object Create
IdentitiesSupported  

可选:

 è  IProfileReaderProvider
è  IProfileWriterProvider

 

2.5.Authorization 模块

2.5.1. 开发应用

è  在自定义的solution里加入Block提供的Common, Security两个Project

è  新建Providers项目, 用来处理Authorization的逻辑之用. 引用CommonSecurity项目

è  创建自定义的Provider class, 必须:Based on IAuthorizationProvider并实现它的三个方法

这里介绍使用XMLAzMan管理用户权限两种开发应用方法

1)        使用XML

如附件中Providers项目下的Authorization/AzXmlProvider.cs. 主要是CheckAccess 方法中根据当前用户的请求, AzXmlProvider.xml 对应配置位置检查用户是否有权限执行任务.

2)        使用AzMan

如果使用AzMan(windows 2003 administration tools/windows 2000 server sp4中自带的Authorization Manager), 则要引用Microsoft.Interop.Security.AzRoles.

方法简介:

1.       c:/windows/system32下找到azRoles.dll

2.       使用.net 1.1自带的tlbimp command line 工具将azroles.dll这个COM dll转换: tlbimp azroles.dll /out: Microsoft.Interop.Security.AzRoles.dll /namespace: Microsoft.Interop.Security.AzRoles

3.       Providers项目再引用Microsoft.Interop.Security.AzRoles.dll

4.       Authorization ManagerMMC上设置用户权限()

如附件中Providers项目下的Authorization/AzManProvider.cs. 实现IAuthorizationProvider 的三个方法都是调用AzMan的方法.

2.5.2. Configuration的设置

设置要引用的Provider

如附件的app.config:      

<authorizationProviders>

         <provider name="azmanProvider" type="Microsoft.ApplicationBlocks.Security.Authorization.AzManProvider, Microsoft.ApplicationBlocks.Security.Providers">

              <storeLocation>msxml://c:/AzMan.xml storeLocation>

              <identitiesSupported>

                   <identityName>primaryIdentity identityName>

              identitiesSupported>

         provider>

         <provider name="AzXmlProvider" type="Microsoft.ApplicationBlocks.Security.Authorization.AzXmlProvider, Microsoft.ApplicationBlocks.Security.Providers">

              <storeLocation>AzXmlProvider.xml storeLocation>

              <identitiesSupported>

                   <identityName>primaryIdentity identityName>

              identitiesSupported>

         provider>

authorizationProviders>

 

附件定义了两个Authorization Provider: Microsoft.ApplicationBlocks.Security.Authorization.AzManProviderMicrosoft.ApplicationBlocks.Security.Authorization.AzXmlProvider标识名分别是azmanProvider, AzXmlProvider.

应用Provider, 见代码:

ExtendedPrincipal principal =      ExtendedPrincipal.Create(Thread.CurrentPrincipal.Identity);

             

principal.AuthorizationProvider =

     "azmanProvider"; // or AzXmlProvider;

 

2.6.    Profile模块

, 不重点介绍, 具体的请见附件DemoApp项目下的Form1.cs

3.总结

1)        Authorization and Profile Application Block 1.0提供了接口, 可以让我们自定义Provider 来灵活实现用户的验证授权动作.

2)        权限分配可以细分到operation, 而且用户权限完全基于Authorization Manager(XML等配置)来自由设置

3)        使用非常方便, 有效地提高验证授权的开发质量

 

4.  参考资料

序号

名称

来源

1

Help for Auth Pro AB 1.0

Block的安装目录

2

Designing Application-Managed Authorization.pdf

 

3

MS - Building Secure ASP.NET Applications.pdf

 

4

 

 

5

 

 

6

 

 



Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=210682


<template> <view class="container"> <!-- 顶部用户信息区域 --> <view class="user-info-section"> <view class="avatar-container"> <image src="/static/workbanch/banner/workbench/4.jpg" class="avatar-image" mode="aspectFill" /> <view class="avatar-frame"></view> </view> <!-- 用户信息 --> <view class="user-details"> <text class="welcome-text">您好,</text> <text class="username">{{ userName || '加载中...' }}</text> <view class="user-meta"> <text class="user-role">{{ userRole }}</text> <text class="user-dept">{{ userDept }}</text> <text class="user-phone" v-if="userPhone">电话:{{ userPhone }}</text> </view> </view> </view> <!-- 功能板块区域 --> <view class="function-section"> <!-- 重置密码按钮 --> <view class="function-item" @click="handleResetPassword" @touchstart="handleTouchStart('reset')" @touchend="handleTouchEnd('reset')" > <view class="item-left"> <image src="/static/workbanch/icons/reset-password.png" class="item-icon" /> <text class="item-text">重置密码</text> </view> <view v-if="showResetModal" class="modal-overlay" @click.self="closeResetModal"> <view class="modal-content"> <input v-model="oldPassword" type="password" placeholder="请输入旧密码" /> <input v-model="newPassword" type="password" placeholder="请输入新密码" /> <input v-model="confirmPassword" type="password" placeholder="请确认新密码" /> <view class="modal-buttons"> <button @click="submitResetPassword">保存</button> <button @click="closeResetModal">关闭</button> </view> </view> </view> <view class="arrow-icon">›</view> </view> <!-- 分隔线 --> <view class="divider"></view> <!-- 退出登录按钮 --> <view class="function-item logout-item" @click="handleLogout" @touchstart="handleTouchStart('logout')" @touchend="handleTouchEnd('logout')" > <view class="item-left"> <image src="/static/workbanch/icons/logout.png" class="item-icon" /> <text class="item-text">退出登录</text> </view> <view class="arrow-icon">›</view> </view> </view> </view> </template> <script setup> import { ref } from 'vue'; import { onShow, onTabItemTap } from '@dcloudio/uni-app'; // 用户信息相关 const userName = ref(''); const userRole = ref(''); const userDept = ref(''); const userPhone = ref(''); // 重置密码 const showResetModal = ref(false); const oldPassword = ref(''); const newPassword = ref(''); const confirmPassword = ref(''); // 触摸状态 const touchState = ref({ reset: false, logout: false }); // 页面显示时加载数据 onShow(() => { // console.log('onShow 被触发'); loadUserInfo(); // 加载用户信息 }); // tabbar 页面被点击时触发 onTabItemTap(() => { // console.log('tabbar 页面被点击'); loadUserInfo(); // 强制刷新数据 }); const forceRefresh = true; // 加载用户信息 const loadUserInfo = async () => { try { const userInfo = uni.getStorageSync('userInfo'); // console.log('本地缓存 userInfo:', userInfo); if (!forceRefresh && userInfo && userInfo.userName) { // 使用缓存 userName.value = userInfo.nickName || userInfo.userName || '未知用户'; userRole.value = userInfo.roles?.[0]?.roleName || '普通用户'; userDept.value = userInfo.dept?.deptName || '未分配部门'; userPhone.value = userInfo.phonenumber || '暂无电话'; } else { // console.log('开始请求用户信息...'); const res = await uni.request({ url: 'http://172.26.26.43/dev-api/system/user/profile', method: 'GET', header: { 'Authorization': 'Bearer ' + uni.getStorageSync('token') } }); // console.log('接口返回结果:', res); if (res.statusCode === 200 && res.data.code === 200) { const userData = res.data.data; uni.setStorageSync('userInfo', userData); userName.value = userData.nickName || userData.userName || '未知用户'; userRole.value = userData.roles?.[0]?.roleName || '普通用户'; userDept.value = userData.dept?.deptName || '未分配部门'; userPhone.value = userData.phonenumber || '暂无电话'; } else { uni.showToast({ title: '获取用户信息失败', icon: 'none' }); uni.redirectTo({ url: '/pages/login/login' }); } } } catch (error) { console.error('加载用户信息失败:', error); uni.showToast({ title: '加载用户信息失败', icon: 'none' }); uni.redirectTo({ url: '/pages/login/login' }); } }; // 处理触摸开始 const handleTouchStart = (type) => { touchState.value[type] = true; }; // 处理触摸结束 const handleTouchEnd = (type) => { touchState.value[type] = false; }; // 显示弹窗 const handleResetPassword = () => { uni.vibrateShort(); // 震动反馈 showResetModal.value = true; }; // 关闭弹窗 const closeResetModal = () => { showResetModal.value = false; }; // 提交重置密码 const submitResetPassword = async () => { const { oldPassword: oldPass, newPassword: newPass, confirmPassword: confirmPass } = { oldPassword: oldPassword.value, newPassword: newPassword.value, confirmPassword: confirmPassword.value }; if (!oldPass || !newPass || !confirmPass) { uni.showToast({ title: '所有密码都必须填写', icon: 'none' }); return; } if (newPass !== confirmPass) { uni.showToast({ title: '新密码与确认密码不一致', icon: 'none' }); return; } uni.showLoading({ title: '提交中...' }); try { const res = await uni.request({ url: 'http://172.26.26.43/dev-api/system/user/profile/updatePwd', method: 'POST', header: { 'Authorization': 'Bearer ' + uni.getStorageSync('token'), 'Content-Type': 'application/json' }, data: { oldPassword: oldPass, newPassword: newPass } }); uni.hideLoading(); if (res.statusCode === 200 && res.data.code === 200) { uni.showToast({ title: '密码修改成功', icon: 'success' }); uni.removeStorageSync('token'); uni.removeStorageSync('userInfo'); setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }); }, 1500); } else { uni.showToast({ title: '密码修改失败', icon: 'none' }); } } catch (error) { uni.hideLoading(); uni.showToast({ title: '网络请求失败', icon: 'none' }); console.error('请求失败:', error); } closeResetModal(); }; // 处理退出登录 const handleLogout = () => { uni.vibrateShort(); // 添加震动反馈 uni.showModal({ title: '确认退出', content: '您确定要退出当前账号吗?', confirmText: '退出登录', confirmColor: '#e74c3c', success: (res) => { if (res.confirm) { // 清除用户相关数据 uni.removeStorageSync('token'); uni.removeStorageSync('userInfo'); uni.removeStorageSync('savedUsername'); // 显示退出提示 uni.showToast({ title: '已退出登录', icon: 'success', duration: 1500 }); // 跳转到登录页 setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }); }, 1500); } } }); }; </script> <style lang="scss" scoped> .container { padding: 20rpx; background-color: #f5f7fa; min-height: 100vh; } /* 用户信息区域样式 */ .user-info-section { display: flex; align-items: center; padding: 30rpx; margin: 20rpx 0; background: linear-gradient(135deg, #3498db, #8e44ad); color: white; position: relative; overflow: hidden; border-radius: 24rpx; &::before { content: ''; position: absolute; top: -50%; right: -50%; width: 200%; height: 200%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 70%); pointer-events: none; } } .user-phone { display: block; font-size: 24rpx; // margin-top: 10rpx; color: rgba(255, 255, 255, 0.8); background: rgba(255, 255, 255, 0.2); padding: 4rpx 12rpx; border-radius: 20rpx; backdrop-filter: blur(10px); } .avatar-container { position: relative; width: 120rpx; height: 120rpx; margin-right: 30rpx; } .avatar-image { width: 100%; height: 100%; border-radius: 50%; background-color: #fff; } .avatar-frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 4rpx solid rgba(255, 255, 255, 0.3); border-radius: 50%; box-sizing: border-box; } .user-details { flex: 1; } .welcome-text { font-size: 28rpx; opacity: 0.9; } .username { display: block; font-size: 40rpx; font-weight: bold; margin: 8rpx 0; text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2); } .user-meta { display: flex; flex-wrap: wrap; gap: 15rpx; margin-top: 15rpx; } .user-role, .user-dept { font-size: 24rpx; background: rgba(255, 255, 255, 0.2); padding: 4rpx 12rpx; border-radius: 20rpx; backdrop-filter: blur(10px); } /* 功能板块区域 - 宽度优化 */ .function-section { background-color: #fff; border-radius: 24rpx; margin: 30rpx 40rpx; /* 左右边距增加 */ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); overflow: hidden; } .function-item { display: flex; align-items: center; justify-content: space-between; padding: 30rpx 35rpx; /* 增加左右内边距 */ position: relative; transition: all 0.2s ease; /* 点击效果 - 缩放 */ &:active { transform: scale(0.98); background-color: #f8f8f8; } /* 触摸效果 - 高亮 */ &.touch-active { background-color: #f0f9ff; transform: scale(0.98); .item-text { font-weight: bold; } } } .logout-item { .item-text { color: #e74c3c; } &.touch-active { background-color: #fff0f0; } } .item-left { display: flex; align-items: center; } .item-icon { width: 44rpx; height: 44rpx; margin-right: 20rpx; transition: transform 0.2s ease; .touch-active & { transform: scale(1.1); } } .item-text { font-size: 32rpx; color: #333; transition: all 0.2s ease; .touch-active & { transform: translateX(5px); } } .arrow-icon { font-size: 40rpx; color: #999; transform: scale(1.5, 1.5); transition: all 0.2s ease; .touch-active & { transform: scale(1.5, 1.5) translateX(-5px); } } .divider { height: 1rpx; background-color: #f0f0f0; margin: 0 35rpx; /* 与内边距一致 */ } /* 动画效果 */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .pulse { animation: pulse 0.3s ease; } //重置密码 .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 9999; } .modal-content { background-color: #fff; padding: 30rpx; border-radius: 20rpx; width: 80%; box-sizing: border-box; display: flex; flex-direction: column; gap: 20rpx; } .modal-content input { border: 1px solid #ddd; padding: 20rpx; border-radius: 10rpx; } .modal-buttons { display: flex; justify-content: space-between; gap: 20rpx; } .modal-buttons button { flex: 1; } </style> 帮我优化一下这段代码,尤其是重置密码弹窗这块,点击重置密码出现弹窗后我在输入过程中每次点击弹窗都会弹一下,点击返回没有隐藏该弹窗并返回该界面,点击保存没有效果
08-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值