Writing XAML applications for use in the Sitecore shell can be very tricky. And I admit that I often decide to use a webform instead. Especially if I need to write a minor application that does not use Sitecore data as such, but still needs to be a part of the Sitecore desktop.
One of the solutions is to implement my own Generic Identity and use declarative security in my webform. And it’s quite easy too. This code can be expanded, but I have kept it simple to demonstrate the principals. Implementing yout own security context requires a generic identity (a user) and a generic principal (a list of groups). The generic identity looks like this:
using System.Security.Permissions; using System.Collections.Generic; using System.Threading; using System.Security.Principal; /// <summary> /// Class imlementing a generic identity /// which equals one Sitecore user /// </summary> public class SitecoreIdentity : IIdentity { private Sitecore.Security.Accounts.User _user; public SitecoreIdentity() { _user = Sitecore.Context.User; } #region IIdentity Members public string AuthenticationType { // I cheat a little bit. Sitecore returns an empty AuthenticationType // so I use the domain name as authenticationtype instead get { return Sitecore.Context.Domain.Name; } } public bool IsAuthenticated { get { return _user.Identity.IsAuthenticated; } } public string Name { get { return _user.Name; } } #endregion }
An identity is accompanied by a principal, which equals the roles that the identity (user) belongs to:
/// <summary> /// Class implementing a generic principal /// which equals the groups one sitecore user /// belongs to /// </summary> public class SitecorePrincipal : IPrincipal { private List<string> _roles = new List<string>(); private IIdentity _identity; private Sitecore.Security.Accounts.User _user; public SitecorePrincipal(IIdentity identity) { _identity = identity; _user = Sitecore.Context.User; // I add the administrator as a role to my principal so I can query it // when using declarative security if (Sitecore.Context.User.IsAdministrator) _roles.Add("Administrator"); // Add all role names from the current user to my principal foreach (Sitecore.Security.Accounts.Role userRole in _user.Roles) { _roles.Add(userRole.Name); } } #region IPrincipal Members public IIdentity Identity { get { return _identity; } } public bool IsInRole(string role) { return _roles.Contains(role); } #endregion }
I can now assign the current thread’s principal of the current webform to my own principal:
void Page_Load(object sender, System.EventArgs e) { // Create new user SitecoreIdentity user = new SitecoreIdentity(); // Assign the roles to that user SitecorePrincipal roles = new SitecorePrincipal(user); // Assign the roles to the current thread Thread.CurrentPrincipal = roles; }
My webform is now runing under the security context of my Sitecore user, and I can now use declarative security to allow or disallow execution of code. The following function will only execute if a Sitecore user is authenticated:
[PrincipalPermission(SecurityAction.Demand, Authenticated=true)] private void WriteText() { Response.Write("Authentication: " + Thread.CurrentPrincipal.Identity.AuthenticationType); Response.Write("Is authenticated: " + Thread.CurrentPrincipal.Identity.IsAuthenticated); Response.Write("Name: " + Thread.CurrentPrincipal.Identity.Name); }
It is the PrincipalPermission attribute that sets the security on my function. If the current Sitecore user is not logged in, .net will throw an exception.
Here is another example. This will allow access if the user is a Sitecore administrator, and block everyone else:
[PrincipalPermission(SecurityAction.Demand, Role="Administrator")] private void WriteText() { // ... your code here }
Pingback: XAML (SheerUI) dialog in Sitecore 6.3.x « Brian Pedersen’s Sitecore and .NET Blog
Pingback: Get Sitecore System Info | Brian Pedersen's Sitecore and .NET Blog
Pingback: Which of my old Sitecore posts are still valid in Sitecore 9? | Brian Pedersen's Sitecore and .NET Blog