Recognizing ASP.NET MVC security trimming request in AuthorizeAttribute override - asp.net-mvc

I have a controller with a custom Authroize attribute on a method:
class ItemsController
[MyAuthorize]
ActionResult MyMethod()
I also use Kendo ASP.NET MVC to create a menu. Kendo provide a great feature with Security trimming where if I try to add a menu item to MyMethod, as Kendo is building the menu, it will check if the current user will have access to the MyMethod action. I don't know how this works or is done.
The issue I am running into is that my code in MyAuthorizeAttribute.AuthorizeCore() logs when a user makes a request and is not authenticated or authorized to view the requested page. This works great except when the user doesn't have access to one of the pages in the menu. Somehow Kendo triggers the MyAuthorizeAttribute.AuthorizeCore() code for the action/controller that the menu item points to. That's all fine except I don't want to log that. The user didn't make a request to the action/controller, it is just an internal check.
So my question is, is there a way for me to determine if the call to MyAuthorizeAttribute.AuthorizeCore() is a security trimming request or an actual page request?

Related

Refresh a Sitecore rendering after logon

I feel like this should be obvious, but I'm stumped. We're running Sitecore 7.1 with MVC.
There is a Header rendering that includes conditional logic depending on the status of Sitecore.Context.IsLoggedIn. Works fine.
There is a second rendering that either allows the user to log in OR displays account information. When the [HttpGet] acton is called, the controller checks IsLoggedIn and returns one of two views. When the [HttpPost] action is called (i.e. when the user logs in), The controller calls AuthenticationManager.Login() and then returns the view with the account info. Works fine.
It's a simple solution that allows us to place one rendering on the page, and it works great, except for one thing: the header rendering still shows the not-logged-in content immediately after logging in.
Caching is turned off on the header rendering and in the presentation details. When any link is clicked or the page reloads, the header updates to show the correct info. The problem is only after the initial request/response, when the login form submits and returns an alternate view. Although we've had a complete HTTP request/response cycle, it's like Sitecore doesn't bother to check anything except the rendering that was directly affected.
I know I can solve this by returning a hard Redirect() after logging in but that seems inelegant and creates annoyances, like losing ViewBag info.
What I am really looking for is a way to tell Sitecore, "hey, refresh that other rendering!"
The fact that I can find nothing at all on-line about this 'problem' tells me I might be doing something conceptually wrong.
As I see it there are two ways of handling this problem:
FormHandler
You use #Html.FormHandler to specify a Controller and an Action to handle the authentication. The FormHandler action will execute very early (see: https://twitter.com/dmo_sc/status/480001473745399809) in the page execution, before anything is rendered, and all your Renderings will have the same view of whether users are logged in or not.
Martina did a good writeup on Sitecore MVC and forms:
https://mhwelander.net/2014/05/28/posting-forms-in-sitecore-mvc-part-1-view-renderings/
https://mhwelander.net/2014/05/30/posting-forms-in-sitecore-mvc-part-2-controller-renderings/
Post-Redirect-Get
I really want Sitecore MVC to have this feature build in, as it is useful for all form submission scenarios (bar AJAX). The idea is to handle the POST request and work out what you want to respond (and store this in tempdata). Instead of returning a ViewResult you issue a redirect to the same URL, this forces a GET to the page (at this point all the logged in state is same for all Renderings) where you fish the result out of tempdata. Also P-R-G protects against resubmitting POST requests.
cprakash documented his experience doing P-R-G:
https://cprakash.com/2015/01/12/sitecore-mvc-form-post-simplified/
Off Topic: Multiple forms on single page
This will not solve the OP problem, but worth having a look at in this context:
http://reinoudvandalen.nl/blog/ultimate-fix-for-multiple-forms-on-one-page-with-sitecore-mvc/
In MVC, your renderings are executed sequentially, top to bottom. So if your header rendering comes before the login status rendering, it's going to be done before the user is logged in.
The elegant way to do this would probably be to do your post and update both elements via JavaScript. If you want to keep the header logic separate from the login status logic, your login status script could allow other components to register their own callbacks. You could even build out a client-side message bus, if you will be doing this sort of thing frequently.
You could take a look at Jeremy's approach:
https://jermdavis.wordpress.com/2016/04/04/getting-mvc-components-to-communicate/
The key takeaway, I think, is where he switches the order of the placeholders by placing the results into variables and then render them wherever you want them.
#{
HtmlString main = Html.Sitecore().Placeholder("MAIN");
HtmlString head = Html.Sitecore().Placeholder("HEAD");
}
<head>
#head
</head>
<body>
#main
</body>

Open new window from GSP and forward to external URL

I need some help. I am converting a Struts application to Grails.
There is a particular action I am trying to convert.
There is a form in a jsp that asks a user to select a customer from a dropdown list and the user clicks one of two buttons.
When the user clicks on the "View Reports" button, an onclick event calls a javascript function that issues window.open on a STRUTS action class, passing the selected customer and selected action.
In the action class the http request has some attributes set (request.setAttribute (..)) and a forward is performed to an external application. The attributes that where set are used by the application for sign on. This is done as a POST.
My problem is I am not quite sure how to wire this flow using the Grails framework. I was able to get as far as the user selecting a customer, clicking an actionSubmit button, reading the selected customer from params, adding my attributes to 'request' and then..I am stuck.
How to open a new window? (Tried javascript way as was done with Struts).
Also I am able to issue a redirect to the external site in the controller, however a redirect is done as a GET and not a POST, as well as the redirect is done in the same window. Any help in laying this out would be awesome. Thanks
You can't redirect a user from server using POST.
I can see some possible solutions:
1 . If you don't need to pass through your server to validate or request some data, you can use this:
<form action="http://someotherserver.com" method="post">
2 . Create a controller that redirect to a page in your own site and in this page make a treatment that receives the paramters and then redirect the user to another domain using ajax.
In Grails, I've used createLink, with the 'base' attribute to do this.
<g:createLink base="${params.dynamicURL}">Link</g:createLink>
I think something like this would work, but you can research it here: http://grails.org/doc/latest/ref/Tags/createLink.html

Custom ActionFilter for disabling the BACK button

Currently working on an ASP.NET MVC 3.0 application and using FormsAuthentication.
When the user clicks the Logoff link, it calls the following:
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
Works great!
But if the user clicks the BACK button, he gets to see his previous page (although he won’t be able to do anything since the [Authorize] attribute is set) and we didn’t want that.
After many searches and posts regarding this subject, I ended up creating a custom ActionFilter called [NoCache] which is placed right underneath each [Authorize] attribute I have.
The [NoCache] attribute looks like this:
public class NoCacheAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
}
}
It seems to work but I’m curious to know if this seems like the appropriate approach to use (or not). Are there any known issues I’m not aware of in using this technique?
In addition, I’ve been told that if I had an SSL Certificate then I wouldn’t need to do this but instead, create and set an HTTP Header with Cache-Control: no-cache which would, ultimately, make all my https pages not cached.
Can anyone confirm this?
If the above is true, then why would I create a custom ActionFilter?
Feel free to share any thoughts or better approaches…
Keep in mind, the ultimate goal is to make sure a user does not see his previous page(s) when clicking the BACK button after he’s been signed off (FormsAuthentication.SignOut();)
Thanks
Would using RedirectToActionPermanent("Index", "Home") work for you? I think it will prevent them returning to the immediately previous page (maybe not all).
Scott Hanselman recommended changing the application design to a Post/Redirect/Get PRG Model when a similar question was asked here.
UPDATE:
A third option is to generate a unique token for every page and invalidate the previous token upon every request. Here is an answer to a similar question that even mentions a bank using that methodology.
Conclusion:
I’ve decided to close this post with the following conclusion…
The PRG Model suggestion (and link) provided by Shawn is great and indeed should be practiced while developing MVC applications.
The pattern makes sure users who hit refresh (F5) are not re-submitting the form/data again. So it is a question of making proper redirect after a form submission.
As for my issue, I wanted to show the login page to the users that did try and hit the back button only after they’ve signed off (After FormsAuthentication.SignOut).
The behavior I am looking for is the same as when you logoff a banking web site. You are free to hit the back button but they will display a message letting you know that your session has expired (which in turn, you are forced to login again.)
I haven’t found (or worked on) a solution yet but the custom NoCache Attribute seems to be the way to go.
Once in production, I will have an SSL certificate applied to the protected pages and perhaps, when we get there, I might find a different way to achieve my task without the use of the NoCache Attribute.
When and if I do, I will share my findings.
Thanks

Remember grid filter state between requests

I'm using Telerik asp.net mvc extensions.
In my application in most cases I'm using the following flow:
Show Grid
Click on the button and perfom business action
Redirect back to Grid.
The problem is that when the user chose some filter in 1. then this filter is lost in 3. Additionally it is kind of annoying when the user chooses from the menu action to show grid and the last used filter is not applied.
Grid filters are stored in URL (GET method).
Such as:
http://localhost/IncomingRequest?IncomingRequestGrid-page=1&IncomingRequestGrid-orderBy=IncomingDate-desc&IncomingRequestGrid-groupBy=~&IncomingRequestGrid-filter=IncomingDate~gt~datetime'2011-10-20T08-10-11'~and~CartNumber~endswith~'xx'
What I would want is to remember filter state between requests. Is this doable?
Please have a look at this thread. you can persist filter sorting and paging. The solution is for ajax binding for server binding you may follow this post

What is a postback?

I'm making my way into web development and have seen the word postback thrown around. Coming from a non-web based background, what does a new web developer have to know about postbacks? (i.e. what are they and when do they arise?)
Any more information you'd like to share to help a newbie in the web world be aware of postbacks would be most greatly appreciated.
The following is aimed at beginners to ASP.Net...
When does it happen?
A postback originates from the client browser. Usually one of the controls on the page will be manipulated by the user (a button clicked or dropdown changed, etc), and this control will initiate a postback. The state of this control, plus all other controls on the page,(known as the View State) is Posted Back to the web server.
What happens?
Most commonly the postback causes the web server to create an instance of the code behind class of the page that initiated the postback. This page object is then executed within the normal page lifecycle with a slight difference (see below). If you do not redirect the user specifically to another page somewhere during the page lifecycle, the final result of the postback will be the same page displayed to the user again, and then another postback could happen, and so on.
Why does it happen?
The web application is running on the web server. In order to process the user’s response, cause the application state to change, or move to a different page, you need to get some code to execute on the web server. The only way to achieve this is to collect up all the information that the user is currently working on and send it all back to the server.
Some things for a beginner to note are...
The state of the controls on the posting back page are available within the context. This will allow you to manipulate the page controls or redirect to another page based on the information there.
Controls on a web form have events, and therefore event handlers, just like any other controls. The initialisation part of the page lifecycle will execute before the event handler of the control that caused the post back. Therefore the code in the page’s Init and Load event handler will execute before the code in the event handler for the button that the user clicked.
The value of the “Page.IsPostBack” property will be set to “true” when the page is executing after a postback, and “false” otherwise.
Technologies like Ajax and MVC have changed the way postbacks work.
From wikipedia:
A Postback is an action taken by an
interactive webpage, when the entire
page and its contents are sent to the
server for processing some information
and then, the server posts the same
page back to the browser.
Expanding on the definitions given, the most important thing you need to know as a web-developer is that NO STATE IS SAVED between postbacks. There are ways to retain state, such as the Session or Viewstate collections in ASP.NET, but as a rule of thumb write your programs where you can recreate your state on every postback.
This is probably the biggest difference between desktop and web-based application programming, and took me months to learn to the point where I was instinctively writing this way.
Postback happens when a webpage posts its data back to the same script/dll/whatever that generated the page in the first place.
Example in C# (asp.net)
...
if (!IsPostback)
// generate form
else
process submitted data;
Web developement generally involves html pages that hold forms (<form> tags). Forms post to URLs. You can set a given form to post to any url you want to. A postback is when a form posts back to it's own page/url.
The term has special significance for ASP.Net WebForms developers, because it is the primary mechanism driving a lot of the behavior for a page — specifically 'event handling'. ASP.Net WebForms pages have exactly one server form which nearly always posts back to itself, and these postbacks trigger execution on the server of something called the Page Lifecycle.
The term is also used in web application development when interacting with 3rd party web-service APIs
Many APIs require both an interactive and non-interactive integration. Typically the interactive part is done using redirects (site 1 redirects a user to site 2, where they sign in, and are redirected back). The non-interactive part is done using a 'postback', or an HTTP POST from site 2's servers to site 1's servers.
When a script generates an html form and that form's action http POSTs back to the same form.
Postback is essentially when a form is submitted to the same page or script (.php .asp etc) as you are currently on to proccesses the data rather than sending you to a new page.
An example could be a page on a forum (viewpage.php), where you submit a comment and it is submitted to the same page (viewpage.php) and you would then see it with the new content added.
See: http://en.wikipedia.org/wiki/Postback
Postback refers to HTML forms. An HTML form has 2 methods: GET and POST. These methods determine how data is sent from the client via the form, to the server. A Postback is the action of POSTing back to the submitting page. In essence, it forms a complete circuit from the client, to the server, and back again.
A post back is anything that cause the page from the client's web browser to be pushed back to the server.
There's alot of info out there, search google for postbacks.
Most of the time, any ASP control will cause a post back (button/link click) but some don't unless you tell them to (checkbox/combobox)
Yet the question is answered accurately above, but just want to share my knowledge .
Postback is basically a property that we can use while doing some tasks that need us to manage the state of the page, that is either we have fired some event for e.g. a button click or if we have refreshed our page.
When our page loads for the very first time , that is if we have refreshed our page, at that time postback-property is false, and after that it becomes true.
if(!ispostback)
{
// do some task here
}
else
{
//do another task here
}
http://happycodng.blogspot.in/2013/09/concept-of-postback-in.html

Resources