Ich habe schließlich meine eigene IdentityUser-Klasse und Schnittstelle implementiert. Dann verwendet, dass als Basis individuellen Users, Usertable, ApplicationUserManager und AppPassword Klassen in meiner Anwendung zu schreiben, die Verwendung von Referenz auf einen WCF-Dienst gemacht, um die notwendigen Daten zu erhalten
using System;
using System.Data;
using System.Data.SqlClient;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using System.Security.Cryptography;
using System.Text;
namespace ProudSourcePrime.Identity
{
/// <summary>
/// Class that represents the Users table in our database.
///
/// It actually does not connect to our database anymore.
///
/// The data it recives for this implementation comes from a service reference running on our data service server.
/// </summary>
/// <typeparam name="TUser"></typeparam>
public class UserTable<TUser> where TUser : IdentityUser
{
/// <summary>
/// sql query that will retrive the username of this user account, keying off of the userId
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public string GetUserName(string userId)
{
string userName = null;
// TODO : sql query that will retrive the username of this user account, keying off of the userId
return userName;
}
/// <summary>
/// sql query that will retrive the userId of this user account, keying off of the userName
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public string GetUserId(string userName)
{
string userId = null;
// TODO : sql query that will retrive the userId of this user account, keying off of the userName
return userId;
}
/// <summary>
/// sql query to get our user data
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public TUser GetUserById(string userId)
{
TUser user = null;
ServiceReference1.Service1Client ProudSoureService = new ServiceReference1.Service1Client();
ServiceReference1.UserRecordComposite userComposite = ProudSoureService.get_UserById(userId);
user = (TUser)Activator.CreateInstance(typeof(TUser));
user.AccessFailedCount = userComposite.AccessFailedCount;
user.Email = userComposite.Email;
user.Id = userComposite.Id;
user.LockoutEnabled = userComposite.LockoutEndDateUtc;
user.Name = userComposite.Name;
user.PasswordHash = userComposite.PasswordHash;
user.PhoneNumber = userComposite.PhoneNumber;
user.PhoneNumberConfirmed = userComposite.PhoneNumberConfirmed;
user.SecurityStamp = userComposite.SecurityStamp;
user.TwoFactorEnabled = userComposite.TwoFactorEnabled;
user.UserName = userComposite.UserName;
return user;
}
/// <summary>
/// sql query to retrive user using username
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public TUser GetUserByUserName(string userName)
{
TUser user = null;
ServiceReference1.Service1Client ProudSourceService = new ServiceReference1.Service1Client();
ServiceReference1.UserRecordComposite userComposite = ProudSourceService.get_UserByUserName(userName);
user = (TUser)Activator.CreateInstance(typeof(TUser));
user.AccessFailedCount = userComposite.AccessFailedCount;
user.Email = userComposite.Email;
user.Id = userComposite.Id;
user.LockoutEnabled = userComposite.LockoutEndDateUtc;
user.Name = userComposite.Name;
user.PasswordHash = userComposite.PasswordHash;
user.PhoneNumber = userComposite.PhoneNumber;
user.PhoneNumberConfirmed = userComposite.PhoneNumberConfirmed;
user.SecurityStamp = userComposite.SecurityStamp;
user.TwoFactorEnabled = userComposite.TwoFactorEnabled;
user.UserName = userComposite.UserName;
return user;
}
/// <summary>
/// sql query for password hash of this user keying off of the userId
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public string GetPasswordHash(string userId)
{
return new ServiceReference1.Service1Client().get_PasswordHash(userId);
}
/// <summary>
/// Sql command that actually created the user record and inserts into it the passwordHash, usernam and Guid Id.
/// </summary>
/// <param name="user"></param>
/// <param name="passwordHash"></param>
/// <returns></returns>
public bool SetPasswordHash(TUser user, string passwordHash)
{
return new ServiceReference1.Service1Client().set_PasswordHash(user.Id, passwordHash, user.UserName, user.Name);
}
/// <summary>
/// Sql command that actually creates the user record and inserts into it the passwordHash, and Guid Id.
///
/// No in use currently SetPasswordHash(TUser user, string passwordHash) gets called.
/// </summary>
/// <param name="userId"></param>
/// <param name="passwordHash"></param>
/// <returns></returns>
public bool SetPasswordHash(string userId, string passwordHash)
{
bool result = false;
//
return result;
}
/// <summary>
/// sql query that retrives the security stamp for this user record
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public string GetSecurityStamp(string userId)
{
string securityStamp = null;
// TODO : sql query that retrives the security stamp for this user record
return securityStamp;
}
/// <summary>
/// sql query that will update a Users table record with the given security stamp
/// </summary>
/// <param name="userId"></param>
/// <param name="securityStamp"></param>
/// <returns></returns>
public bool SetSecurityStamp(string userId, string securityStamp)
{
bool result = false;
// TODO : sql query that sets the security stamp of a user record
return result;
}
/// <summary>
/// sql query that inserts a new user into our data base
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public bool Insert(TUser user)
{
bool result = false;
// TODO : sql query that inserts a new User entry
return result;
}
/// <summary>
/// sql query to delete this user from our table
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public bool Delete(TUser user)
{
bool result = false;
// TODO : sql query to delete this user from our table
return result;
}
/// <summary>
/// sql query that will update our user record on our Users table
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public bool Update(TUser user)
{
bool result = false;
// TODO : sql query that will update our user record on our Users table
return result;
}
}
/// <summary>
/// Class that implements ASP.NET IUserPasswordStore, IUserSecurityStamp and IUserStore off of the concrete impemntations of IdentityUser's methods.
/// </summary>
/// <typeparam name="TUser"></typeparam>
public class UserStore<TUser> : IUserStore<TUser>, IUserPasswordStore<TUser> where TUser : IdentityUser
{
/// <summary>
/// Private resident that gives access to UserTable's concrete methods
/// </summary>
private UserTable<TUser> userTable;
/// <summary>
/// Default Constructor that initializes a new UserTable with connection to our data base.
/// </summary>
public UserStore()
{
userTable = new UserTable<TUser>();
}
/// <summary>
/// Insert a new user into our Users table.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public Task CreateAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
// This is commented out for now
//
// New User is actually created in method SetPasswordHash(TUser user, string passwordHash).
//userTable.Insert(user);
return Task.FromResult<object>(null);
}
/// <summary>
/// Delete a user from our Users table.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public Task DeleteAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
userTable.Delete(user);
return Task.FromResult<object>(null);
}
void IDisposable.Dispose()
{
throw new NotImplementedException();
}
/// <summary>
/// Retrives a user by using an Id.
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public Task<TUser> FindByIdAsync(string userId)
{
if (string.IsNullOrEmpty(userId))
{
throw new ArgumentNullException("user");
}
return Task.FromResult(userTable.GetUserById(userId));
}
/// <summary>
/// Find a user by using the username.
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public Task<TUser> FindByNameAsync(string userName)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentNullException("TUser is null");
}
return Task.FromResult(userTable.GetUserByUserName(userName));
}
/// <summary>
/// Returns the passwordhash for a given TUser
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public Task<string> GetPasswordHashAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
return Task.FromResult(userTable.GetPasswordHash(user.Id));
}
/// <summary>
/// Get the security stamp for a given TUser.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public Task<string> GetSecurityStampAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
return Task.FromResult(userTable.GetSecurityStamp(user.Id));
}
/// <summary>
/// Verfies whether a given TUser has a password.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public Task<bool> HasPasswordAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
if (!string.IsNullOrEmpty(userTable.GetPasswordHash(user.Id)))
{
return Task.FromResult(true);
}
else
{
return Task.FromResult(false);
}
}
/// <summary>
/// Sets the password hash for a given TUser.
/// </summary>
/// <param name="user"></param>
/// <param name="passwordHash"></param>
/// <returns></returns>
public Task SetPasswordHashAsync(TUser user, string passwordHash)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
if(userTable.SetPasswordHash(user, passwordHash))
{
return Task.FromResult("true");
}
else
{
return Task.FromResult("false");
}
}
/// <summary>
/// This method will set the secrity stamp for a given TUser.
/// </summary>
/// <param name="user"></param>
/// <param name="stamp"></param>
/// <returns></returns>
public Task SetSecurityStampAsync(TUser user, string stamp)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
if(userTable.SetSecurityStamp(user.Id, stamp))
{
return Task.FromResult("true");
}
else
{
return Task.FromResult("false");
}
}
/// <summary>
/// This method will update a given TUser
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public Task UpdateAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
if(userTable.Update(user))
{
return Task.FromResult("true");
}
else
{
return Task.FromResult("false");
}
}
}
/// <summary>
/// Implementation of the UserManager class that will be handeling verification and
/// </summary>
public class ApplicationUserManager : UserManager<IdentityUser>
{
/// <summary>
/// Class instantiation.
/// </summary>
/// <param name="store"></param>
public ApplicationUserManager(UserStore<IdentityUser> store) : base(store)
{
Store = store;
this.PasswordHasher = new AppPassword();
UserLockoutEnabledByDefault = false;
// this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10);
// this.MaxFailedAccessAttemptsBeforeLockout = 10;
UserValidator = new UserValidator<IdentityUser>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
// Configure validation logic for passwords
PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
}
/// <summary>
/// Override that actually uses the base layer implementation thus exposing it's funtionality through this object.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public override System.Threading.Tasks.Task<IdentityResult> CreateAsync(IdentityUser user, string password)
{
return base.CreateAsync(user, password);
}
}
/// <summary>
/// Custom password hasher and hash comparison implementor.
/// </summary>
public class AppPassword : IPasswordHasher
{
/// <summary>
/// Method that hashes passwords.
/// </summary>
/// <param name="password"></param>
/// <returns></returns>
public string HashPassword(string password)
{
using (SHA256 sha = SHA256Managed.Create())
{
byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(password.ToString()));
StringBuilder hashSB = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
hashSB.Append(hash[i].ToString("x2"));
}
return hashSB.ToString();
}
}
/// <summary>
/// Method that compares a given password hash with an input password and compares the given password hash with the hash of the input password.
/// </summary>
/// <param name="hashedPassword"></param>
/// <param name="providedPassword"></param>
/// <returns></returns>
public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{
string providedPassword_hashed = HashPassword(providedPassword);
if (hashedPassword.Equals(providedPassword_hashed))
{
return PasswordVerificationResult.Success;
}
else
{
return PasswordVerificationResult.Failed;
}
}
}
}
hier ist IdentityUser
using Microsoft.AspNet.Identity;
using System;
namespace ProudSourcePrime.Identity
{
/// <summary>
/// Class that implements ASP.NET Identity IUser interface.
/// </summary>
public class IdentityUser : IUser
{
public string Id { get; set; }
public string UserName { get; set; }
public virtual string Email { get; set; }
public virtual string PasswordHash { get; set; }
public virtual string SecurityStamp { get; set; }
public virtual string PhoneNumber { get; set; }
public virtual bool PhoneNumberConfirmed { get; set; }
public virtual bool TwoFactorEnabled { get; set; }
public virtual DateTime? LockoutEnabled { get; set; }
public virtual int AccessFailedCount { get; set; }
public virtual string Name { get; set; }
/// <summary>
/// Default constructor that generates a new guid.
/// </summary>
public IdentityUser()
{
Id = Guid.NewGuid().ToString();
}
/// <summary>
/// Constructor that accepts a Username as a parameter.
/// </summary>
/// <param name="userName"></param>
public IdentityUser(string userName) : this()
{
UserName = userName;
}
/// <summary>
/// Public accessor to this IdentityUsers GUID
/// </summary>
string IUser<string>.Id
{
get
{
return Id;
}
}
/// <summary>
/// Public accessor to this IdentityUsers UserName
/// </summary>
string IUser<string>.UserName
{
get
{
return UserName;
}
set
{
UserName = value;
}
}
}
}
Dann Implementiert ich AppUserPrincipal die ClaimsPrincipal erbt Ansprüche und AppViewPage vererben WebViewPage zu genehmigen, so dass alle Seiten auf der Website sind heute ein AppViewPage Typ, aber immer noch erben, was notwendig ist, in geeigneter Weise
using System.Security.Claims;
using System.Web.Mvc;
namespace ProudSourcePrime.Config
{
public class AppUserPrincipal : ClaimsPrincipal
{
public AppUserPrincipal(ClaimsPrincipal principal) : base(principal)
{
}
public string Name
{
get
{
return this.FindFirst(ClaimTypes.Name).Value;
}
}
}
public abstract class AppController : Controller
{
public AppUserPrincipal CurrentUser
{
get
{
return new AppUserPrincipal(this.User as ClaimsPrincipal);
}
}
}
/// <summary>
/// Custom base view page to be inherited by all Razor Views in the web application.
///
/// This provides access too our AppUser principal.
/// </summary>
/// <typeparam name="TModel"></typeparam>
public abstract class AppViewPage<TModel> : WebViewPage<TModel>
{
protected AppUserPrincipal CurrentUser
{
get
{
return new AppUserPrincipal(this.User as ClaimsPrincipal);
}
}
}
public abstract class AppViewPage : AppViewPage<dynamic>
{
}
}
zu laufen
Ich machte dann ein Web.Config nicht im Verzeichnis root aber tatsächlich innerhalb der Ordner Sichten, dass für die MVC-Projekt und dort ich die Website konfigurieren meine AppViewPage Klasse musste ich nur sicherstellen, dass zu meinen Dienst Verweis auf das Projekt verwenden
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<!--<pages pageBaseType="System.Web.Mvc.WebViewPage">-->
<pages pageBaseType="ProudSourcePrime.Config.AppViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Optimization "/>
<add namespace="ProudSourcePrime" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
<add key="owin:AppStartup" value="Startup"/>
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
<system.web>
<compilation>
<assemblies>
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
</system.web>
</configuration>
Dann fügen und stellen Sie sicher, dass der Dienst die erforderlichen Daten zurückgibt und dass er bereit war zu gehen.
Hier ist ein Link zu dem Projekt, das auf meinem GitHub ist. Bevor Sie gehen ohh noes gibt es interne IPs hier und sensitive Informationen! Ich weiß, und es ist mir egal, dass die Server-Umgebung, in der es untergebracht ist, von allen Änderungen, die nicht über den öffentlich zugänglichen Webserver gehen, abgeschottet ist und dass nur der Webserver vom offenen Web aus erreichbar ist. Selbst ich habe keinen Zugang mehr und ich habe das absichtlich gemacht, so dass niemand darauf zugreifen konnte und es wird bald verschwinden.
https://github.com/jewishmexicanguy/ProudSourcePublic/tree/master/Staging/Herzon/Csharp_codebehnid/ProudSourcePrime
Dieses Projekt war für eine Fintech Startup, das heute nicht mehr existierenden, da die drei Gründer (ich und zwei andere) in andere Dinge zu wagen entschieden.
Für den Fall, dass Sie das Endergebnis sehen möchten, gehen Sie hier, es wird bald verschwinden, seit ich für das Konto bezahlt habe. http://proudsource.us/welcome
Haben Sie sich diese [http://stackoverflow.com/questions/24910304/how-to-use-asp-net-identity-model-for-wcf-service-authorization-and- Authenticati) Frage? –
Wenn Sie WCF für die mittlere Schicht verwenden, können Sie WebAPI nicht verwenden. Warum auch eine andere mittlere Schicht? –
Ich wollte eine vollständige Trennung zwischen der Client-orientierten Web-App und dem Datendienst haben. Damit meine ich, dass der Datendienst auf einem separaten Server innerhalb eines Subnetzes mit mittlerer Vertrauenswürdigkeit gehostet wird, und von dort aus muss dieser Server alle SQL-Abfragen durchführen, die für einen SQL-Server in einem Subnetz mit hoher Vertrauenswürdigkeit erforderlich sind. Ich habe nichts gegen WebAPI ich bin nur nicht damit vertraut. –