Sitecore 4 developers are familiar with the login rendering concept: It
is possible for any rendering to have its counterpart login rendering
which gets shown if the user doesn't have required permission to access
content.
I'll use SDN as an example - try to access an item that
anonymous user is not allowed to read, like
http://sdn.sitecore.net/articles.ascx. You can still see the layout.
Moreover, top menu renders items accessible to the current user
(Documentation is a public section) and the breadcrumb shows your
correct location (home / articles) even though you cannot see the item
itself.
The main content rendering (the one in the centre) shows
the 'please login' info because it has the login rendering set, and
Sitecore layout engine knows that the current user (anonymous) is not
allowed to access the current item (/home/articles).
The concept
is fundamentally changed in Sitecore 5 because of one difference: if
the current user is not allowed to access the current page, he is
redirected to:
1. Login page if the login page is specified for the current site, controlled by the loginPage property of each individual site.
2. No access page, controlled by NoAccessUrl setting in web.config.
in any way, he won't be able the access the item as he used to in Sitecore 4 at SDN, even without the content.
This
logic is baked in the ExecuteRequest processor in httpRequestBegin
pipeline. It’s not easy to change it though (I've moved the
explanation
to the end of the post to avoid clutter). And it's not a good idea to
modify bunch of processors only to make things as they were before
anyway. Two common requirements for scenarios when user is not allowed
to access content he tries to are:
1. User is presented with a friendly message explaining what happened.
2. Along with the friendly message, user can login and see the page he's trying to access.
Login page supports both:
1.
Create a new item, and allow 'read' for everyone. Locate your site in
the <sites> section of web.config, and set a loginPage property:
<sites>
<website loginPage="/home/login.aspx" .. />
</sites>This
item will probably have the default layout of the site, but instead of
the content rendering it should have a 'login rendering' explaining
that a user has to login to access the item.
2. When redirecting
to login page, Sitecore will fill two query string parameters: 'item'
and 'login'. This solves the last requirement - how to redirect user
back to the requested item.
I've made a little class to handle this for sdn/spn sites, here's how it can be used:
DomainAccessResult result = new LoginManager().Login(emailTextBox.Value, passwordTextBox.Value);It performs the usual Sitecore.Context.Domain.Login() and
a) redirects user back to the requested item if any
b) redirects user to 'login failed page' if it’s specified either in web.config or class property.
download link:
LoginManager.cs
--
If you allow all users to see restricted pages
and allow ItemResolver processor (earlier in the same pipeline) to set
the Sitecore.Context.Item property - you're creating a possible
security hole. Renderings do not perform explicit permission check
every time they need to output some content - having the
Sitecore.Context.Item set is enough to know that the item meets all
criteria and can be shown.
The other option is to leave
standard ItemResolver processor but still modify ExecuteRequest: this
way user will be redirected to layout but Sitecore.Context.item will
remain null. Security is ok this way, but because context item is not
set Sitecore layout engine has no clue which item user wanted to access
(and wasn't able to) - therefore it cannot decide (among other things)
whether it should show the login rendering or not.