It is possible that you don't store your member data in Umbraco database any longer and you have got an external service that provides your member data, so that your web users can login to your website using this external service. If this is the case then you might see the following error happening in the background which is also causing some performance issues.
An error occurred in GetCurrentMember. System.InvalidOperationException: No member object found with username [email protected] at umbraco.cms.businesslogic.member.Member.GetCurrentMember()
This exception is most likely happening due to your project references to built in Umbraco membership provider, hence first step should be checking your Umbraco project's Web.config for UmbracoMembershipProvider. If the setting is similar to the following, then this is the reason that you see these exceptions. In that case, follow the 3 steps below to fix this problem.
<add name="UmbracoMembershipProvider" type="Umbraco.Web.Security.Providers.MembersMembershipProvider, Umbraco" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="10" useLegacyEncoding="false" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Member" passwordFormat="Hashed" allowManuallyChangingPassword="false" />
Step 1: Custom membership provider: Create a new custom Membership provider, derive it from Umbraco's MembersMembershipProvider. Override all the methods and only update the methods that you need according to your project's needs. For my case, I only need GetUser method to return the logged in user data.
using System; using System;
using System.Linq;
using System.Web.Security;
using Umbraco.Web.Security.Providers;
namespace MYPROJECT.Web.Presentation.Security
{
///
<summary>
/// Custom
membership provider that we use to replace the normal Umbraco one as we are not
storing any members in the standard Umbraco membership system.
/// Instead
members are logging in using SSO and using claims based auth, claims are
provided by both MYPROJECT SSO and additionally come from Crm Api
/// It is almost
entirely unimplemeted apart from the GetUser method which is called by various
umbraco functions especially from a few places in Umbraco Forms
/// All other
methods will throw a NotImplemented Exception
///
</summary>
/// <remarks>
/// We have to
inherit the Umbraco membership provider rather than the standard
System.Web.Security.Membership otherwise umbraco roles don't work
/// when
protecting content using Umbraco public access UI due to this Umbraco issue
https://github.com/umbraco/Umbraco-CMS/issues/5469
///
</remarks>
public class
MYPROJECTMembershipPvovider : MembersMembershipProvider
{
///
<summary>
/// Returns a
user based on the username.
/// As we do
not have any backing store to look up user details this will only ever return a
user if username requested is the currently logged in user.
/// In this
case we can get the details from the current claims principle, otherwise we
will return null
///
</summary>
/// <param
name="username"></param>
/// <param
name="userIsOnline"></param>
///
<returns></returns>
public
override MembershipUser GetUser(string username, bool userIsOnline)
{
//If no
username then just return null
if
(string.IsNullOrWhiteSpace(username))
{
return
null;
}
//check
requested user is the same as the current logged in user
if
(System.Security.Claims.ClaimsPrincipal.Current?.Identity?.Name == username)
{
var cp
= System.Security.Claims.ClaimsPrincipal.Current;
//Try
and extract crm contactId from the users claims (where we put it during login)
var
crmIdClaim = cp.Claims.FirstOrDefault(i => i.Type ==
Services.IdentityService.CrmContactIdClaim)?.Value;
Guid?
crmContactId = null;
if
(crmIdClaim != null)
{
crmContactId = Guid.Parse(crmIdClaim);
}
var
user = new MYPROJECTMembershipUser(
Membership.Provider.Name, //Providername
cp.Claims.FirstOrDefault(i => i.Type == "name")?.Value,
//Name
crmContactId, // provideruserkey
cp.Claims.FirstOrDefault(i => i.Type == Services.IdentityService.EmailClaim)?.Value,
//email
null, //password question
null, //comment
true, //isApproved
false, //isLockedOut
DateTime.MinValue, //creation
date
DateTime.Now, //last login date
DateTime.Now, //last activity date
DateTime.MinValue, //last pasword change
DateTime.MinValue, //last
lockout date
crmContactId);
return
user;
}
else
{
return
null;
}
}
#region
#region NotImplemented Properties and Methods
public
override string DefaultMemberTypeAlias
{
get
{
throw
new NotImplementedException();
}
}
public override
MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
throw new
NotImplementedException();
}
public
override bool ChangePassword(string username, string oldPassword, string
newPassword)
{
throw new NotImplementedException();
}
public
override bool ChangePasswordQuestionAndAnswer(string username, string password,
string newPasswordQuestion, string newPasswordAnswer)
{
throw new
NotImplementedException();
}
public
override MembershipUser CreateUser(string username, string password, string
email, string passwordQuestion, string passwordAnswer, bool isApproved, object
providerUserKey, out MembershipCreateStatus status)
{
throw new
NotImplementedException();
}
public
override bool DeleteUser(string username, bool deleteAllRelatedData)
{
throw new
NotImplementedException();
}
public
override MembershipUserCollection FindUsersByEmail(string emailToMatch, int
pageIndex, int pageSize, out int totalRecords)
{
throw new
NotImplementedException();
}
public
override MembershipUserCollection FindUsersByName(string usernameToMatch, int
pageIndex, int pageSize, out int totalRecords)
{
throw new
NotImplementedException();
}
public
override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out
int totalRecords)
{
throw new
NotImplementedException();
}
public
override int GetNumberOfUsersOnline()
{
throw new
NotImplementedException();
}
public
override string GetPassword(string username, string answer)
{
throw new
NotImplementedException();
}
public
override string GetUserNameByEmail(string email)
{
throw new
NotImplementedException();
}
public
override string ResetPassword(string username, string answer)
{
throw new
NotImplementedException();
}
public
override bool UnlockUser(string username)
{
throw new
NotImplementedException();
}
public
override void UpdateUser(MembershipUser user)
{
throw new
NotImplementedException();
}
public
override bool ValidateUser(string username, string password)
{
throw new
NotImplementedException();
}
protected
override MembershipUser PerformCreateUser(string memberTypeAlias, string
username, string password, string email, string passwordQuestion, string
passwordAnswer, bool isApproved, object providerUserKey, out
MembershipCreateStatus status)
{
throw new
NotImplementedException();
}
protected
override bool PerformChangePassword(string username, string oldPassword, string
newPassword)
{
throw new
NotImplementedException();
}
protected override bool
PerformChangePasswordQuestionAndAnswer(string username, string password, string
newPasswordQuestion, string newPasswordAnswer)
{
throw new
NotImplementedException();
}
protected
override string PerformGetPassword(string username, string answer)
{
throw new
NotImplementedException();
}
protected
override string PerformResetPassword(string username, string answer, string
generatedPassword)
{
throw new NotImplementedException();
}
#endregion
NotImplemented Properties and Methods
}
}
Step 2: Custom Membership User: Create your custom membership user.
using System;
using System.Web.Security;
namespace MYPROJECT.Web.Presentation.Security
{
///
<summary>
/// Represents a
logged in MYPROJECT user, inherits standard membership user and adds additional
fields that we need populated from claims
///
</summary>
public class MYPROJECTMembershipUser
: MembershipUser
{
public Guid?
CrmContactId { get; private set; }
public MYPROJECTMembershipUser(string
providerName,
string
name,
object
providerUserKey,
string email,
string
passwordQuestion,
string
comment,
bool
isApproved,
bool isLockedOut,
DateTime
creationDate,
DateTime
lastLoginDate,
DateTime
lastActivityDate,
DateTime
lastPasswordChangedDate,
DateTime
lastLockoutDate,
Guid?
crmContactId) : base(
providerName, name, providerUserKey, email, passwordQuestion, comment,
isApproved, isLockedOut, creationDate, lastLoginDate, lastActivityDate,
lastPasswordChangedDate, lastLockoutDate)
{
CrmContactId = crmContactId;
}
}
}
Step 3: Change in the Umbraco project's Web.config: Change UmbracoMembershipProvider to use your custom membership provider class.
<add name="UmbracoMembershipProvider" type="MYPROJECT.Web.Presentation.Security.MYPROJECTMembershipPvovider, MYPROJECT.Web.Presentation" />
That is all, hope this helps!
Comments
Post a Comment