我们的网站使用ASP角色和成员资格提供程序系统进行表单身份验证。我们已将文件组织到文件夹中,这些文件夹通过文件夹web.config文档强制执行授权列表(例如:您必须具有Admin角色才能访问〜/ Admin文件夹中的页面)并且我们不允许匿名(未登录)访问除了站点根目录。站点在IIS7.5上托管,带有.Net 4.0绑定和脚本映射。
利益相关方现在要求我们允许PIN针对特定用例进行身份验证,用户尚未拥有凭据,但已收到带PIN的信件。
我们编写了一个堆栈来验证用于身份验证的PIN,但我们没有办法告诉他们会员/角色API他们现在是登录用户,因为他们使用PIN绕过我们的SSO。
当操作员提供有效的引脚时,我需要找到一种临时为匿名会话分配角色的方法,这样他们就可以利用文件夹中不允许匿名访问的页面。
我已经看到有迹象表明您可以将个人资料信息与匿名用户联系起来,但我一直无法找到有关为用户(会话确实)分配角色的任何信息。
是否有人有任何想法为匿名用户分配角色,以便他们可以浏览需要特定角色的授权列表?
答案 0 :(得分:1)
尝试扩展ClaimsAuthenticationManager
。您可以覆盖Authenticate
。这应该允许您将您的PIN用户视为经过身份验证,并允许您分配角色。
public class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{...
您可以在ClaimsAuthenticationManager
(或Global.asax.cs
)中激活展开的.vb
。此示例来自ASP.NET MVC应用程序。 (你没有提到你是使用MVC还是WebForms。)
public class MvcApplication : System.Web.HttpApplication
{
...
protected void Application_PostAuthenticateRequest()
{
var principal = ClaimsPrincipal.Current;
var transformer = new ClaimsTransformer();
var newPrincipal = transformer.Authenticate(string.Empty, principal);
Thread.CurrentPrincipal = newPrincipal;
HttpContext.Current.User = newPrincipal;
}
}
答案 1 :(得分:1)
弗兰克,
以下是我在一家不再工作的公司使用的一段代码。
首先,这是一个常量和私有变量列表:
private const int LOGON_PROVIDER_DEFAULT = 0;
private const int LOGON_LOGON_INTERACTIVE = 2;
private const string m_domain = "PLACE YOUR ACTIVE DIRECTORY DOMAIN NAME HERE";
private const string m_sUser = "PLACE YOUR ADMINISTRATOR ACCOUNT'S USERNAME HERE";
private const string m_sPassword = "PLACE YOUR m_sUser PASSWORD HERE";
private static string m_lastUser = null;
private static DirectoryEntry m_rootDir;
private WindowsImpersonationContext m_impersonatedUser;
public enum SECURITY_IMPERSONATION_LEVEL {
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3
}
[DllImport("advapi32.dll", SetLastError = true)] // obtains user token
private static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] // closes open handes returned by LogonUser
private extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] // creates duplicate token handle
private extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
所有这些都用于我的课程中,模仿,这会使任何Windows帐户冒充 m_sUser :
private void Impersonate() {
IntPtr pExistingTokenHandle = IntPtr.Zero;
IntPtr pDuplicateTokenHandle = IntPtr.Zero;
m_lastUser = Environment.UserName;
bool bImpersonated = LogonUser(m_sUser, m_domain, m_sPassword, LOGON_LOGON_INTERACTIVE, LOGON_PROVIDER_DEFAULT, ref pExistingTokenHandle);
if (bImpersonated) {
try {
bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);
if (bRetVal) { // create new identity using new primary token
using (var newId = new WindowsIdentity(pDuplicateTokenHandle)) {
m_impersonatedUser = newId.Impersonate();
m_rootDir = new DirectoryEntry(m_ldapPath);
}
} else { // did DuplicateToken fail?
int nErrorCode = Marshal.GetLastWin32Error();
string sResult = "DuplicateToken() failed with error code: " + nErrorCode + GSTR.CRLF;
MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
} catch (Exception err) {
MessageBox.Show(err.Message, "ADWrapper Error");
} finally {
m_working = false;
if (!pDuplicateTokenHandle.Equals(IntPtr.Zero)) {
CloseHandle(pDuplicateTokenHandle);
pDuplicateTokenHandle = IntPtr.Zero;
}
if (!pExistingTokenHandle.Equals(IntPtr.Zero)) {
CloseHandle(pExistingTokenHandle); // close existing handle
pExistingTokenHandle = IntPtr.Zero;
}
}
} else {
int nErrorCode = Marshal.GetLastWin32Error();
string sResult = "LogonUser() failed with error code: " + nErrorCode + GSTR.CRLF;
MessageBox.Show(sResult, "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
当我第一次运行时,它在.NET Framework 2.0上运行,但在我离开之前它已升级到.NET 4.0。
我使用的是静态帐户,该帐户在我们的网络中设置为管理员,但您可能会看到如何修改此帐户以使用您的PIN验证具有某个用户名的用户。
不要忘记调用下面的Dispose()
方法恢复为默认用户。如果包含此代码的类实现 IDisposable ,那么如果您忘记了GC,则很有可能被GC调用:
public void Revert() {
if (m_impersonatedUser != null) {
m_impersonatedUser.Undo();
m_impersonatedUser = null;
}
if (m_rootDir != null) {
m_rootDir.Close();
Global.Dispose(m_rootDir);
m_rootDir = null;
}
}
public void Dispose() {
Revert();
}
同样,我不再在该公司工作,因此我无法为您测试特定项目或告诉您特定场景返回的值类型。
我希望这会有所帮助。祝你好运!