[編輯:增加了UserService代碼]identityserver3定製usersevice不會被調用
當我IdentityServer內將下面的代碼已經在ADUserService說和.UseInmemory(MemUser.TempUser)代碼不予置評,一切工作正常。
當InMemory被標記並且兩個ADUserService行沒有標記爲下面的代碼時,將顯示相同的登錄屏幕,但是這次失敗。在調試時,沒有顯示日誌,並且在登錄期間沒有輸入ADUserService,但僅在調用啓動代碼期間。
我錯過了什麼嗎?難道我做錯了什麼?
// identityServer factory
var factory = new IdentityServerServiceFactory()
// .UseInMemoryUsers(MemUser.TempUser) // Fix: Remove temp users!!
.UseInMemoryClients(CrbAuthClients.Get())
.UseInMemoryScopes(Scopes.AllSupportedScopes);
var userService = new ADUserService();
factory.UserService = new Registration<IUserService>(resolver => userService);
// identityServer go!!
var options = new IdentityServerOptions
{
SigningCertificate = Certificate.Load(),
AuthenticationOptions = new AuthenticationOptions
{
SignInMessageThreshold = 1 // default is 5, prevents "Header Too Long" error
},
Factory = factory
};
app.UseIdentityServer(options);
難道這是由於我使用Visual Studio和IIS快遞在HTTPS是不是無論是IDServ3服務器(南錫)或我的MVC客戶端驗證?
難道我需要添加CORS策略服務嗎?我什麼時候需要這個?我從單獨的MVC項目和網站調用身份驗證。
factory.CorsPolicyService = new Registration<ICorsPolicyService>(new DefaultCorsPolicyService { AllowAll = true });
難道是因爲我以前使用inMem用戶的問題,現在有某種緩存的地方還在使用? (我查了鮑勃 - 祕密制止了變更後的工作,並改回時對內存中的用戶返回工作)
----- -----編輯
也許是因爲對我沒有使用ldapConnectionDelegate? 我需要嗎?
下面的代碼:
namespace Crb.Auth.AuthServer.Securing
{
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading.Tasks;
using System.DirectoryServices;
using System.Security.Claims;
using System.DirectoryServices.AccountManagement;
using IdentityServer3.Core;
using IdentityServer3.Core.Services;
using IdentityServer3.Core.Models;
using IdentityServer3.Core.Extensions;
using IdentityServer3.Core.Services.Default;
using Serilog;
// according to gist https://gist.github.com/rmbrunet/6c5c2ba2b8fb03fbc359
// from rmbrunet on Stack Exchange here: https://github.com/IdentityServer/IdentityServer3/issues/1366
// A slightly cleaner but less explicit approach (not used here) is in https://gist.github.com/tjrobinson/0ad6c790e90d7a385eb1
// from rajarameshvarma on Stack Exchange here: https://github.com/IdentityServer/IdentityServer3/issues/995
// Startup code is taken from the CustomUserService project in the IdentityServer3 Samples.
public class ADUserService : UserServiceBase //UserServiceBase
{
static class ADAttributes
{
public static string SamAccountName = "samaccountname";
public static string Mail = "mail";
public static string UserGroup = "usergroup";
public static string DisplayName = "displayname";
public static string Department = "department";
public static string StreetAddress = "streetAddress";
public static string Phone = "telephoneNumber";
public static string State = "st";
public static string City = "l";
public static string Zip = "postalCode";
public static string Surname = "sn";
public static string Givenname = "givenName";
}
const string ActiveDirectoryConnectionStringname = "CnnActiveDir";
#region setup and construction
//Func<string, string> _ldapConnectionDelegate; //Delegate that receives the domain and returns the LDAP connection string.
// default ctor reads from connection string
public ADUserService()//Func<string, string> ldapConnectionDelegate)
{
//_ldapConnectionDelegate = ldapConnectionDelegate;
//Log.Debug("ADUserService called");
}
//.. region setup and construction
#endregion
#region authenticate with claims
#region authenticate external - not supported
public System.Threading.Tasks.Task<IdentityServer3.Core.Models.AuthenticateResult> AuthenticateExternalAsync(IdentityServer3.Core.Models.ExternalIdentity externalUser, IdentityServer3.Core.Models.SignInMessage message)
{
return Task.FromResult<AuthenticateResult>(null);
}
#endregion
public Task<AuthenticateResult> AuthenticateLocalAsync(
string userDomainAndName, // sometimes referred to as 'the subject'
string password,
SignInMessage message)
{
bool isUserValid = false;
if (string.IsNullOrEmpty(userDomainAndName)
|| userDomainAndName.IndexOf(@"\") < 1) // expected: some domain name given followed by a backslash
{
Log.Debug("Supplied username missing domain. Authentication denied.");
return Task.FromResult<AuthenticateResult>(null); // Failed!!
}
var split = userDomainAndName.ToLower().Split('\\'); //username assumed to be in the form domain\user
string domain = split[0];
string username = split[1];
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
{
isUserValid = pc.ValidateCredentials(username, password);
}
if (!isUserValid)
{
Log.Debug("Authentication attempt failed for {0}", userDomainAndName);
return Task.FromResult<AuthenticateResult>(null);
}
return Task.FromResult<AuthenticateResult>(
new AuthenticateResult(subject: username.ToLower(), name: username));
}
#region pre-authenticate async - not supported
public System.Threading.Tasks.Task<IdentityServer3.Core.Models.AuthenticateResult> PreAuthenticateAsync(IdentityServer3.Core.Models.SignInMessage message)
{
return Task.FromResult<AuthenticateResult>(null);
}
#endregion
//..region authenticate
#endregion
#region profile
public System.Threading.Tasks.Task<IEnumerable<System.Security.Claims.Claim>> GetProfileDataAsync(
System.Security.Claims.ClaimsPrincipal principal,
IEnumerable<string> requestedClaimTypes = null)
{
List<System.Security.Claims.Claim> claims = new List<Claim>(); //x null;
string subject = principal.GetSubjectId();
if (! string.IsNullOrEmpty(subject))
claims.Add(new Claim(Constants.ClaimTypes.Subject, subject)); // notice: idsrv3 short name convention as opposed to claims with full type
SearchResult result = findUser(subject);
if (result != null &&
result.Properties.Contains(ADAttributes.Mail) &&
result.Properties.Contains(ADAttributes.DisplayName))
{
claims.Add(new Claim(ClaimTypes.Email, (String)result.Properties[ADAttributes.Mail][0]));
claims.Add(new Claim(ClaimTypes.Name, (String)result.Properties[ADAttributes.DisplayName][0]));
if (result.Properties.Contains(ADAttributes.Surname))
claims.Add(new Claim(ClaimTypes.Surname, (String)result.Properties[ADAttributes.Surname][0]));
if (result.Properties.Contains(ADAttributes.Givenname))
claims.Add(new Claim(ClaimTypes.GivenName, (String)result.Properties[ADAttributes.Givenname][0]));
//Is there an address?
if (result.Properties.Contains(ADAttributes.State)
&& result.Properties.Contains(ADAttributes.StreetAddress)
&& result.Properties.Contains(ADAttributes.City)
&& result.Properties.Contains(ADAttributes.Zip))
{
string state = (String)result.Properties[ADAttributes.State][0];
string street = (String)result.Properties[ADAttributes.StreetAddress][0];
string city = (String)result.Properties[ADAttributes.City][0];
string zip = (String)result.Properties[ADAttributes.Zip][0];
string address = string.Format("{0}, {1}, {2} {3}", street, city, state, zip);
claims.Add(new Claim(ClaimTypes.StreetAddress, address));
}
// Get roles from AD user groups
var prince = principal.Identity as UserPrincipal;
var groups = prince.GetGroups();
foreach (var group in groups)
claims.Add(new Claim(ClaimTypes.Role, "dpn:" + group.DisplayName+",dtn:"+group.DistinguishedName));
claims = claims.Where(x => requestedClaimTypes.Contains(x.Type)).ToList();
}
return Task.FromResult(claims.AsEnumerable());
}
//.. region profile
#endregion
#region sign-out
public System.Threading.Tasks.Task SignOutAsync(System.Security.Claims.ClaimsPrincipal subject)
{
return Task.FromResult(0);
}
//..region sign-out
#endregion
#region internals
SearchResult findUser(string subject)
{
string[] a = subject.Split('\\');
string domain = a[0];
string username = a[1];
string node = ConfigurationManager.ConnectionStrings[ActiveDirectoryConnectionStringname].ConnectionString;
//x _ldapConnectionDelegate(domain);
using (DirectoryEntry searchRoot = new DirectoryEntry(node))
{
using (DirectorySearcher search = new DirectorySearcher(searchRoot))
{
search.Filter = string.Format("(&(objectClass=user)(objectCategory=person)(SAMAccountName={0}))", username);
//search.PropertiesToLoad.Add(Constants.ADAttributes.SamAccountName);
search.PropertiesToLoad.Add(ADAttributes.Mail);
search.PropertiesToLoad.Add(ADAttributes.UserGroup);
search.PropertiesToLoad.Add(ADAttributes.DisplayName);
search.PropertiesToLoad.Add(ADAttributes.Surname);
search.PropertiesToLoad.Add(ADAttributes.Givenname);
search.PropertiesToLoad.Add(ADAttributes.Department);
search.PropertiesToLoad.Add(ADAttributes.StreetAddress);
search.PropertiesToLoad.Add(ADAttributes.Phone);
search.PropertiesToLoad.Add(ADAttributes.State);
search.PropertiesToLoad.Add(ADAttributes.City);
search.PropertiesToLoad.Add(ADAttributes.Zip);
return search.FindOne();
}
}
}
public System.Threading.Tasks.Task<bool> IsActiveAsync(System.Security.Claims.ClaimsPrincipal principal)
{
string subject = principal.GetSubjectId(); // this should return the "distinguished name" (sub.maindomain/username)
SearchResult result = findUser(subject);
return Task.FromResult(result != null);
}
//.. region internals
#endregion
}
}
也許我在做錯的是,我沒有「上下文功能」。 我將編輯問題並添加userService代碼 – pashute