- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
注:Cross-posted to ServerFault ,基于评论。
我需要用密码保护应用程序中的某些操作,例如加载/保存文件、单击复选框等。这是一个标准的 C# .Net 4.0、WinForms 应用程序,将在企业网络中的 Windows 7 上运行。
我本来打算用用户/密码/权限(散列和加盐)的文本文件来滚动我自己的非常基本的系统(通过敞开的后门读取混淆),直到经过一些搜索后,我发现了看起来像 tantalizingly simple approach ,但我很难找到不关于 ASP.NET 的关于角色的优秀教程。
有谁知道一个或多个教程可以告诉我如何:
角色
或权限。
界面
的方法,并且只需询问 Windows 当前用户是否拥有 ABC 权限,而不必太关心 Windows 是如何计算出来的。然后我可以为每个本地/网络/ActiveDirectory/等进行具体的实现。根据需要使用案例(或者如果需要...因为我现在甚至不知道)。- read if interested, but not required to answer question
为了确保我在这里朝着正确的方向前进,基本上我需要/想要在我的开发 PC 上进行测试,以确保它能为我的客户提供良好的最终用户体验。问题是,目前他们为运行我的应用程序的每台计算机运行自动登录脚本,并且有几个不同的运算符(operator)全天使用我的应用程序。客户希望对我的应用程序的某些功能提供密码保护,并且只向某些运营商提供密码保护。我对此没有任何问题,因为我已经预料到这个请求有一段时间了,我只是以前从未编写过身份验证程序。
我认为说服我的客户为每个运算符(operator)提供自己的网络帐户并向该运算符(operator)或组分配他们想要的任何权限是值得的,以防他们需要解雇某人、更改权限等。这也意味着我只需打开为他们提供了多种选择,他们可以根据内部公司政策对这些权限进行分组,但他们认为合适,我真的不必担心(但如果我必须推出自己的政策,就会担心,因为他们的 IT 部门知道)我的应用程序几乎没有任何内容)。
据我所知,它还使我的生活变得更加轻松,因为不必处理散列密码和加密等问题,而只需处理单击这个或那个按钮所需的角色。
最佳答案
首先,您必须确定您是否真的想要一个简单的基于角色的身份验证(您可能需要阅读: http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/ )
如果您确定它绝对足够,那么您在问题中提供的 SO 链接已经走在正确的道路上。令人困惑的是,Windows 默认情况下不支持“角色”,但有组。组可以是本地组或远程组(例如 ActiveDirectory),因此管理员可以将用户分配到特定于您的应用程序的某些组(例如,请参见此处:http://msdn.microsoft.com/en-us/library/ms731200(v=vs.110).aspx)
其中一个关键是:您必须准备应用程序的中央主体,因此为其填充当前用户支持的角色。
因此,在应用程序启动时,您可以检查当前的事件用户并设置应用程序范围的主体和角色。这可能看起来像这样(只是一个非常简单的例子):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Principal;
using System.Text;
using System.Threading;
namespace WindowsPrincipalTrial
{
public class Program
{
// you could also move these definitions to a config file
private static IDictionary<string, string> _groupRoleMappings = new Dictionary<string, string>()
{
{"MYAPPUSERGRP", MyRoles.Standard},
{"MYAPPSUPPORTGRP", MyRoles.Extended},
{"MYAPPADMINGRP", MyRoles.Admin},
};
private static void Main(string[] args)
{
var windowsId = WindowsIdentity.GetCurrent();
if (windowsId != null)
{
var allRoleNames = getGroupCorrespondingRoles(windowsId);
var newPrincipal = new GenericPrincipal(windowsId, allRoleNames);
Thread.CurrentPrincipal = newPrincipal;
}
else
{
throw new NotSupportedException("There must be a logged on Windows User.");
}
}
private static string[] getGroupCorrespondingRoles(WindowsIdentity id)
{
// you also could do this more elegant with LINQ
var allMappedRoleNames = new List<string>();
string roleName;
foreach (var grp in id.Groups)
{
var groupName = grp.Translate(typeof(NTAccount)).Value.ToUpper();
if (_groupRoleMappings.TryGetValue(groupName, out roleName))
{
allMappedRoleNames.Add(roleName);
}
}
return allMappedRoleNames.ToArray();
}
}
public static class MyRoles
{
public const string Standard = "standard_role";
public const string Extended = "extended_role";
public const string Admin = "admin_role";
}
}
然后您的应用程序主体已设置完毕。现在您可以像这样检查代码中的访问权限:
public void DoSomethingSpecial()
{
if (Thread.CurrentPrincipal.IsInRole(MyRoles.Extended))
{
// do your stuff
}
else
{
// maybe display an error
}
}
或者更彻底:
public void DoSomethingCritical()
{
var adminPermission = new PrincipalPermission(null, MyRoles.Admin);
adminPermission.Demand();
// do stuff
}
正如 ASP.NET 所知道的,甚至是声明性的也是可能的:
[PrincipalPermission(SecurityAction.Demand, Role=MyRoles.Admin)]
public void DoSomethingMoreCritical()
{
// do stuff
}
后两个示例的丑陋之处在于,当未命中正确的角色时,它们会抛出异常。
因此,根据您要使用的系统(本地组、AD 组、LDAP 组等),您必须在应用程序启动时就完成角色和组之间的映射。
但是,如果您更喜欢使用操作和角色进行身份验证,请查看 Windows Identity Foundation 和基于声明的授权!已经有一些现成的框架(例如 https://github.com/thinktecture/Thinktecture.IdentityModel )。
更新:
当谈到基于事件并因此基于声明的授权时,我将简单地尝试一下如何通过使用 Thinktecture 的 IdentityModel 来实现它。
通常,这种方法仍然在内部使用角色,但中间有一种转换层。 Thinktecture已经封装了许多需要的东西。然后通过声明权限来完成代码中的授权检查。从技术上讲,它们是访问特定资源的请求。为了简单起见,我通过使用一个默认资源来限制我的示例仅用于操作(因为 ClaimPermission 不接受空资源)。如果您想使用action@resource对,则必须分别修改代码。
首先您需要一个ClaimsAuthorizationManager
public class MyClaimsAuthorizationManager : ClaimsAuthorizationManager
{
private IActivityRoleMapper _actionToRolesMapper;
public MyClaimsAuthorizationManager(IActivityRoleMapper mapper)
{
_actionToRolesMapper = mapper;
}
public override bool CheckAccess(AuthorizationContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
try
{
var action = getActionNameFromAuthorizationContext(context);
var sufficientRoles = _actionToRolesMapper.GetRolesForAction(action)
.Select(roleName => roleName.ToUpper());
var principal = context.Principal;
return CheckAccessInternal(sufficientRoles, principal);
}
catch (Exception ex)
{
return false;
}
}
protected virtual bool CheckAccessInternal(IEnumerable<string> roleNamesInUpperCase, IClaimsPrincipal principal)
{
var result = principal.Identities.Any(identity =>
identity.Claims
.Where(claim => claim.ClaimType.Equals(identity.RoleClaimType))
.Select(roleClaim => roleClaim.Value.ToUpper())
.Any(roleName => roleNamesInUpperCase.Contains(roleName)));
return result;
}
// I'm ignoring resources here, modify this, if you need'em
private string getActionNameFromAuthorizationContext(AuthorizationContext context)
{
return context.Action
.Where(claim => claim.ClaimType.Equals(ClaimPermission.ActionType))
.Select(claim => claim.Value)
.FirstOrDefault();
}
}
正如您可能已经猜到的,IActivityRoleMapper
是一个类的接口(interface),它返回所有角色的名称,其中包括给定操作的权限。这个类非常个性化,我想你会找到实现它的方法,因为这不是这里的重点。您可以通过硬编码、从 xml 或数据库加载来实现。此外,如果您想要使用 action@resource 对来请求权限,则必须更改/扩展它。
然后你必须将 main() 方法中的代码更改为:
using Thinktecture.IdentityModel;
using Thinktecture.IdentityModel.Claims;
using Microsoft.IdentityModel.Web;
private static void Main(string[] args)
{
var windowsId = WindowsIdentity.GetCurrent();
if (windowsId != null)
{
var rolesAsClaims = getGroupCorrespondingRoles(windowsId)
.Select(role => new Claim(ClaimTypes.Role, role))
.ToList();
// just if you want, remember the username
rolesAsClaims.Add(new Claim(ClaimTypes.Name, windowsId.Name));
var newId = new ClaimsIdentity(rolesAsClaims, null, ClaimTypes.Name, ClaimTypes.Role);
var newPrincipal = new ClaimsPrincipal(new ClaimsIdentity[] { newId });
AppDomain.CurrentDomain.SetThreadPrincipal(newPrincipal);
var roleMapper = new ActivityRoleMapper(); // you have to implement
// register your own authorization manager, so IdentityModel will use it per default
FederatedAuthentication.ServiceConfiguration.ClaimsAuthorizationManager = new MyClaimsAuthorizationManager(roleMapper);
}
else
{
throw new NotSupportedException("There must be a logged on Windows User.");
}
}
最后您可以通过这种方式检查访问权限:
public const string EmptyResource = "myapplication";
public void DoSomethingRestricted()
{
if (!ClaimPermission.CheckAccess("something_restricted", EmptyResource))
{
// error here
}
else
{
// do your really phat stuff here
}
}
或者再说一次,但有异常(exception):
private static ClaimPermission RestrictedActionPermission = new ClaimPermission(EmptyResource, "something_restricted");
public void DoSomethingRestrictedDemand()
{
RestrictedActionPermission.Demand();
// play up, from here!
}
声明式:
[ClaimPermission(SecurityAction.Demand, Operation = "something_restricted", Resource = EmptyResource)]
public void DoSomethingRestrictedDemand2()
{
// dostuff
}
希望这有帮助。
关于winforms - 在 WinForms 中验证用户身份(与 ASP.Net 无关),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22873717/
在为 Web 应用程序用例图建模时,为用户可以拥有的每个角色创建一个角色是否更好?或拥有一个角色、用户和一个具有特权的矩阵? guest < 用户 < 版主 < 管理员 1: guest 、用户、版主
我无法使用 Elixir 连接到 Postgres: ** (Mix) The database for PhoenixChat.Repo couldn't be created: FATAL 28P
这个问题已经有答案了: Group by field name in Java (7 个回答) 已关闭 7 年前。 我必须编写一个需要 List 的方法并返回 Map> . User包含 Person
感谢您的帮助,首先我将显示代码: $dotaz = "Select * from customers JOIN contracts where customers.user_id ='".$_SESS
我只想向所有用户中的一个用户显示一个按钮。我尝试了 orderByKey() 但没有成功! 用户模型有 id 成员,我尝试使用 orderByChild("id") 但结果相同! 我什至尝试了以下技巧
我们在工作中从 MongoDB 切换到 Postgres,我正在建立一个 BDR 组。 在这一步,我正在考虑安全性并尽可能锁定。因此,我希望设置一个 replication 用户(角色)并让 BDR
export class UserListComponent implements OnInit{ users; constructor(private userService: UserS
我可以使用 Sonata User Bundle 将 FOS 包集成到 sonata Admin 包中。我的登录功能正常。现在我想添加 FOSUserBundle 中的更改密码等功能到 sonata
在 LinkedIn 中创建新应用程序时,我得到 4 个单独的代码: API key 秘钥 OAuth 用户 token OAuth 用户密码 我在 OAuth 流程中使用前两个。 的目的是什么?最后
所以..我几乎解决了所有问题。但现在我要处理另一个问题。我使用了这个连接字符串: SqlConnection con = new SqlConnection(@"Data Source=.\SQLEX
我有一组“用户”和一组“订单”。我想列出每个 user_id 的所有 order_id。 var users = { 0: { user_id: 111, us
我已经为我的Django应用创建了一个用户模型 class User(Model): """ The Authentication model. This contains the u
我被这个问题困住了,找不到解决方案。寻找一些方向。我正在用 laravel 开发一个新的项目,目前正致力于用户认证。我正在使用 Laravels 5.8 身份验证模块。 对密码恢复 View 做了一些
安装后我正在使用ansible配置几台计算机。 为此,我在机器上本地运行 ansible。安装中的“主要”用户通常具有不同的名称。我想将该用户用于诸如 become_user 之类的变量. “主要”用
我正在尝试制作一个运行 syncdb 的批处理文件来创建一个数据库文件,然后使用用户名“admin”和密码“admin”创建一个 super 用户。 到目前为止我的代码: python manage.
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 6 年前。 Improv
我已在 Azure 数据库服务器上设置异地复制。 服务器上运行的数据库之一具有我通过 SSMS 创建的登录名和用户: https://learn.microsoft.com/en-us/azure/s
我有一个 ionic 2 应用程序,正在使用 native FB Login 来检索名称/图片并将其保存到 NativeStorage。流程是我打开WelcomePage、登录并保存数据。从那里,na
这是我的用户身份验证方法: def user_login(request): if request.method == 'POST': username = request.P
我试图获取来自特定用户的所有推文,但是当我迭代在模板中抛出推文时,我得到“User”对象不可迭代 观看次数 tweets = User.objects.get(username__iexact='us
我是一名优秀的程序员,十分优秀!