在WinForms中对用户进行身份验证(与ASP.Net无关)
注:,根据评论 简介 我需要对应用程序中的某些操作进行密码保护,例如加载/保存文件、单击复选框等。这是一个标准的C#.Net 4.0 WinForms应用程序,将在公司网络的Windows 7上运行 我本来打算用一个包含用户/密码/权限的文本文件(散列和盐析)来运行我自己的非常基本的系统(打开后门阅读模糊处理),直到经过一些搜索之后,我发现了一个 ,但我很难找到一个关于角色的好教程,不是关于ASP.NET的 问题: 那么,是否有人知道一个或多个教程向我展示了如何:在WinForms中对用户进行身份验证(与ASP.Net无关),winforms,c#-4.0,authentication,Winforms,C# 4.0,Authentication,注:,根据评论 简介 我需要对应用程序中的某些操作进行密码保护,例如加载/保存文件、单击复选框等。这是一个标准的C#.Net 4.0 WinForms应用程序,将在公司网络的Windows 7上运行 我本来打算用一个包含用户/密码/权限的文本文件(散列和盐析)来运行我自己的非常基本的系统(打开后门阅读模糊处理),直到经过一些搜索之后,我发现了一个 ,但我很难找到一个关于角色的好教程,不是关于ASP.NET的 问题: 那么,是否有人知道一个或多个教程向我展示了如何: 创建Windows用户/组,并
- 请注意,我正在从我公司的联网笔记本电脑上进行测试,但将在客户的公司网络上部署它(不确定这是否是一个问题,或者这将变得多么棘手)
界面
,只需询问Windows当前用户是否具有ABC权限,而不必太在意Windows是如何解决这个问题的。然后,我可以根据需要为每个本地/Network/ActiveDirectory/等用例做一个具体的实现(或者如果需要的话……我现在还不知道)据我所知,它还使我的生活变得更加轻松,因为它不必处理散列密码和加密等问题,只需处理单击该按钮或该按钮所需的角色。首先,您必须确定是否真的需要简单的基于角色的身份验证(您可能需要阅读:) 如果您确信这是绝对足够的,那么您在问题中提供的SO链接已经走上了正确的道路。在Windows中默认不支持“角色”,但存在组,这有点令人困惑。组可以是本地的,也可以是远程的(例如ActiveDirectory),因此管理员可以将用户分配给特定于您的应用程序的特定组(例如,请看这里:) 一个关键点是:您必须准备应用程序的中心主体,因此用当前用户支持的角色填充它 因此,在应用程序启动时,检查当前活动用户并设置应用程序范围的主体和角色。这可能看起来像这样(只是一个非常简单的例子): 或者更彻底地说:
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
}
后两个例子的丑陋之处在于,当正确的角色未命中时,它们抛出异常
因此,角色和组之间的映射必须在应用程序开始时根据要使用的系统(本地组、广告组、LDAP组等)进行
如果您喜欢使用动作和角色进行身份验证,那么,请查看Windows身份基础和基于声明的授权!已经有一些现成的框架(例如)
更新: 说到基于活动的授权,也就是基于声明的授权,简而言之,我将尝试使用Thinktecture的IdentityModel实现它 一般来说,这种方法仍然在内部使用角色,但中间有一种翻译层。Thinktecture已经封装了许多需要的东西。然后通过声明权限完成代码中的授权检查。从技术上讲,它们是一种访问特定资源的请求。为了简单起见,我将我的示例仅限于操作,只使用一个默认资源(因为Claunpermission不接受空资源)。 如果你想用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();
}
}
最后,您可以通过以下方式检查访问:
public const string EmptyResource = "myapplication";
public void DoSomethingRestricted()
{
if (!ClaimPermission.CheckAccess("something_restricted", EmptyResource))
{
// error here
}
else
{
// do your really phat stuff here
}
}
或者,除了例外:
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
}
希望这能有所帮助。不要无济于事,但设置角色通常不是开发人员的工作或责任。这就是网络管理,最好是服务器故障。一旦网络管理员创建了角色,开发人员就可以检查用户是否在代码中的角色中。如果您需要与管理员一起定义应用程序所需的角色,则情况就不同了。。。这是在一个工作环境中,你需要向网络管理员寻求帮助吗?@DavidStratton我是一个系统集成商,在某些领域
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
}
}
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
}