Struts 2 : investigate request origin - struts2

Our Payroll application needs to be extended with a function that tracks when enter and leave work during the day. We are deploying a JSP page on several terminals around our country.
The JSP page that provides this capability, is part of a big struts2 application.
What we want, is to check the origin of the request, when the JSP page calls an action form one of out terminals. We need to check the IP, match the relative DNS name, and so on.... but this is not the matter!
The matter is: How should we do this ?
I am thinking about to develop an Interceptors that will be attached to all the actions that requires request origin validation.
Do you think this is a good approach?
Does already exists an interceptor that provide this functionality?

i don't know how to check the dns, but if you want to check the origin of the request, which i presume to be client's ip address, you can get it by httpServletRequest.getRemoteAddr(). don't forget to make your action implements ServletRequestAware

Related

Hiding parameters (sensitive information) from URL of an MVC 5 application

I am working on Asp.Net MVC 5. When i click a link (placed in another website) I navigate to UserDetails.cshtml page. Basically that 3rd party site is passing the UserName & Password to my site & using that I authorize & display further user info.
It's fine but the Url is looking like this
localhost:8080//Admin/UserDetails/UserName/PWD.
I don't want to show the UserName & Password in URL i.e URL should look something like :
localhost:8080//Admin/UserDetails/
One possible solution could be rewrite the URL in IIS (http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx)
But I believe there is an easier way to handle this by using the routing mechanism of MVC.
Please help me to figure out the same.
EDIT :
As many of you are confused why I am not doing a Form Post here, let me re-frame my question. I have no control over the third party application, so I cant request them to do a form Post to my MVC application. Again the 3rd party application is a Oracle Reporting application (OBI), so doing a POST from that application might not be feasible too...
Let me reverse engineer your requirements from your question:
I want to have an URI that when invoked will give access to a secured section of my website. This URI must be clicked by visitors of a third-party site, whom I give that URI to. I want to hide the credentials from the URI.
You cannot do this, the requirements are conflicting. You cannot hand out URIs that will authenticate anyone who fires a request to that URI.
You could do something with a token (like http://your-site/auth/$token), but then still, anyone with access to that URI can use it to authenticate themselves, or simply put it up on their own website.
If you have data you want to expose to a third-party site, let that site perform an HTTP request (with tokens, usernames, headers or whatever you want to use to authenticate) in the background to your site, and display the response in their site. Then the visitor won't see that traffic, can't share the URI and all will be secure.
No. No. NO. Like seriously, NO. Any sensitive information should be sent via a post body over a secure connection (HTTPS). You can't "hide" information in a GET request, because it's all part of the URI, or the location of a particular resource. If you remove a portion, it's an entirely different location.
UPDATE
I find it extremely hard to believe that any third-party application that needs to authenticate via HTTP and isn't designed by a chimp with a typewriter, wouldn't support a secure method to do so, especially if it's an Oracle application. I'm not familiar with this particular app, but, and no offense meant here, but I would more easily believe that you've missed something in the documentation or simply haven't found the right way to do it yet before I'd believe you have to send clear-text credentials over GET.
Regardless, as I said previously, there's no way to hide information in a GET request. All data in a GET is part of the URL, and therefore is plainly visible in the browser location bar or whatever. Unfortunately, I have no advice for you other than to look closer at the documentation, even reach out to Oracle if you have to. Whether by post or something like OAuth, there almost has to be another way.

Is there an attribute in MVC to limit Controller Actions to posts from a specific site?

I have an ajax call used to start the 'forgot password' process from an SPA to a controller in the MVC app that looks something like this:
[HttpPost]
public JsonResult ResetPassword(User acct)
{
...
}
I was hoping there was a way to limit this controller to posts only from that page. I could write a custom attribute I suppose, but I was hoping this is a common enough problem that someone has already done that. And yes, I realize falsifying headers to contain spoofed referrer data is possible, but the added layer of security would give me a little more piece of mind. Or does anyone have a suggestion of a better way to accomplish the same thing?
Thanks for the help!
The short answer is that you can't. As noted, you could try to use the referrer header (HttpRequest.Referrer), but it's not reliable for a number of reasons:
It's not a required header,
You're depending on the rendering agent (e.g, the client browser) to set it [honestly], and
It can be changed. For instance, if the request is proxied, it could be set to the proxy URL.
HttpRequest.UserHostAddress is probably somewhat more reliable. But again, you can't really depend on it: it's the IP address the request came from, but again, if the request is proxied or coming through a firewall, you're likely going to get the proxy address, not the actual client IP address.
The most reliable way would be to implement client authentication via a certificate:
http://www.iis.net/configreference/system.webserver/security/authentication/clientcertificatemappingauthentication
http://www.iis.net/configreference/system.webserver/security/authentication/iisclientcertificatemappingauthentication
Though it's a bit of a hassle: the client has to provide the correct cert as part of the request and the server has to have the matching cert as well.
You could check the referer header in HTTP. That gives you the page the request was made from.
Yes, you have to be mindful that this is not secure, as any HTTP header can easily be spoofed.
I think you can use anti forgery token
http://kamranicus.com/blog/posts/70/protip-using-anti-forgery-token-with-aspnet-web-ap/

using ASP.NET MVC, is there a way to capture all POST requests regardless of URL to a host?

I'm having trouble debugging an MVC app that I'm expecting a relying part to POST to.
Is there an easy way to configure an MVC 4 application to intercept all POST requests so I can see what URL it is trying to post to and what the response is?
Normally, a global filter would be what you want. However, since that would not trigger until after the route was determined, it might not help you in this situation.
One thing you could try is to add an Application_BeginRequest method in global.asax. It doesn't even have to do anything. Just set a breakpoint in it, and inspect Request.AppRelativeCurrentExecutionFilePath (or the other members of Request) to see what the inbound path is.
protected void Application_BeginRequest()
{
if (Request.HttpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase))
{ // Breakpoint here
}
}
A "global filter" is the preferred method for injecting behaviors, etc. into the pipeline. MVC already implements some of these, and you can also extend or implement your own.
One concrete example that I implemented last year: client site has feature to expire password. Great; works fine, when the user changes it immediately when told to do so. But they figured out they could just navigate to another portion of the site, and it didn't prompt again until next time they logged in. So we added a global filter that checked whether the password was expired (and whether we'd already checked in this session) and, if so, redirected to the "change password" screen. After changing it, they could return to wherever they were before.
Here's the drawback to this, though, for figuring out a routing or binding issue: the routing engine has already evaluated the request before your global filter can get it. If it fails to identify a target action, your filter won't even be hit. So in this case, a lower-level feature like Application_BeginRequest is your only realistic option.

ASP MVC 3 RequireHttps attribute change all links to https

I have an ASP MVC 3 website that has a Feedback form and should require SSL.
Now, I have an action called Feedback inside a controller called 'ContactUs' that is responsible for viewing and processing the feedback.
When I used the [RequireHttps] attribute on that action, it works nice and it changes the URL to "https". However, I noticed that all the links inside my page are now pointing to "https"! As if this attribute had forced the routing engine to apply the same to all links!!!
Of course, the SSL is only required for this single action and all the rest need to have normal http.
Could anyone tell me how to solve this?
In your case [RequireHttp] attribute might be OK if you clear out the login cookie - or you'll be sending it in clear-text across the wire. It might be more work than it's worth to avoid the slight cost of further HTTPS calls. SO is all about recycling questions and other users reading your question might think it's OK to drop down to HTTP after login, when it's usually the wrong thing to do.
The [RequireHttps] attribute can be used on a controller type or action method to say "this can be accessed only via SSL." Non-SSL requests to the controller or action will be redirected to the SSL version (if an HTTP GET) or rejected (if an HTTP POST). You can override the RequireHttpsAttribute and change this behavior if you wish. There's no [RequireHttp] attribute built-in that does the opposite, but you could easily make your own if you desired.
There are also overloads of Html.ActionLink() which take a protocol parameter; you can explicitly specify "http" or "https" as the protocol. Here's the MSDN documentation on one such overload. If you don't specify a protocol or if you call an overload which doesn't have a protocol parameter, it's assumed you wanted the link to have the same protocol as the current request.
The reason we don't have a [RequireHttp] attribute in MVC is that there’s not really much benefit to it. It’s not as interesting as [RequireHttps], and it encourages users to do the wrong thing. For example, many web sites log in via SSL and redirect back to HTTP after you’re logged in, which is absolutely the wrong thing to do. Your login cookie is just as secret as your username + password, and now you’re sending it in clear-text across the wire. Besides, you’ve already taken the time to perform the handshake and secure the channel (which is the bulk of what makes HTTPS slower than HTTP) before the MVC pipeline is run, so [RequireHttp] won’t make the current request or future requests much faster.
You can create another custom filter attribute to move back to http. Try solution from this question...
Why once SSL is enabled with [RequireHttps] at action level, it remains enabled forever?

Mixed http/https site

So far, my https deployments have commonly involved a naive lockdown of the entire site with https and provide an http-to-https redirect on the web server.
I now plan to have a single ASP.NET MVC site (on the cloud) that will contain both http and https pages. So, the site will have 2 conceptual (not physical) zones providing for both secure and non-secure requests.
Configuration-wise, I have set up input ports for both 80 and 443 and the site accepts both requests.
Is there any way I can flip protocol to https for any call that goes to an action that belongs in the secure zone? For instance, the kind of things that action filters can do.
Thanks much.
edit: Please note that the whole idea of this is to avoid using absolute urls on the form action attribute because of portability issues and because the user will not see the https:// assurance visual cues on the browser.
P
You might want to take a look at the MVC futures assembly from Microsoft available for download here.
This has a FilterAttribute, RequireSslFilterAttribute that allows you to easily tag Action methods in your controller that require SSL - e.g.
[RequireSsl(Redirect=true)]
public ActionResult LogOn()
{
return View();
}
The optional redirect parameter will cause the request to be redirected to the same URL but via https instead of http if required.
WARNING: As Daniel points out though, by the time you hit this Action it may already be too late if data was posted to a non secure version of the page - it is already potentially compromised, so you still need to exercise care when using this and make sure all sensitive data is sent via https. (I just noticed your comment to Daniel, you obviously understand this, I'll leave the warning here for anyone else who stumbles upon this though!)
EDIT: As Luke points out, in MVC2 this attribute is now part of the core framework and is renamed to [RequireHttps]
Is there any way I can flip protocol to https for any call that goes to an action that belongs in the secure zone?
The short answer is no, once the request has come via http, it has already been potentially compromised. You can require that certain calls come via the HTTPS (not sure how to do that as I have not done ASP.Net for awhile) and send an error if they do not. The key is to decide when you want the application to make the jump, ie during login and choose the HTTPS as the action for those forms. Is that what you meant by 'action filters'?

Resources