I'm trying to retrieve an image from a HTTP Handler.
An issue which I'm having is trying to make it so that only the application can access the image, I've tried editing the anonymous IIS authentication to allow the application pool identity but this still lets users through.
Here's an example:
ASPX page makes a call to the handler (picService.ashx?id=1) passing in an ID via query string
HTTP Handler sends back image
The image source is Services/picService.ashx?id=1
This all works fine. Now if a user wanted to go and visit picService.ashx and type in any old ID, it would return the image which correlates to that ID. I'm working with sensitive information so this isn't acceptable.
I've had a look at HTTP Forbidden handlers but I'm not sure whether I'm going down the right route.
I've also tried returning the image in the ASPX page but you can't do this due to the Image control needing a URL.
How can I return an image from a database and have the source of the image be secure?
Should I be doing this a different way? Or am I on the right track (http forbidden)?
A technique I have used in the past is to have the page (step 1) create a GUID, and register a cache item keyed by the GUID that has the actual image URL in the object. The page constructs the url for the handler, using the GUID and passes to the handler
The handler (step 2) then knows to go to cache to get the actual value and return the content.
This way you only expose the temporary "magic" value. Its definitely obfuscation and not a substitute for proper security.
As an example (from memory, syntax may be off a bit)
In the aspx or caller
string keyValue = Guid.NewGuid().ToString();
int yourImageID = 5;
Cache.Add(keyValue, yourImageID) //expire in 5 or 10 seconds
string url = "Handler.ashx?imgID=" + HttpUtility.UrlEncode(keyValue);
Response.Redirect(url, false);
In your handler (I use ashx mostly, choose whatever suits your need)
string key = HttpUtility.UrlDecode(context.Request.QueryString.Get("imgID"));
int yourImageID = (int) context.Cache.Get(key);
//get your image from the db and return the content
Again, just because I used a guid doesn't mean you have to, but if you are trying to obfuscate the IDentity, then choose something that does not correlate to the IDentity.
The way you word your question there is no way to get it 100% secure. So what trade-offs are you willing to allow and what are you not?
What exactly are you trying to prevent? Only one user not seeing another user's image? Or prevent right-click, save image as as well?
One idea that comes to mind is combine the user's ip address with the id of the image, hash that, throw it in a cache (or use a guid as a key to look up those values). Maybe remove it from the cache once that hash is used, therefore only allow the image to be loaded once by one ip per page it is supposed to be on.
You should be able to throw the mapping between a generated ID and real into the session, or HttpRuntime.Cache.Insert(cacheName, cachedValue) Database is probably not the best answer, they are small amounts of data, and you can set the expiration time to a small value, so unless you have millions of users at a time...
Using a Flash control to load the image would be secure in terms of can't right-click save image as. Also probably could encrypt the stream, or split apart the image headers or something if you're worried about someone intercepting the image stream. They could still get a url to the image, but your flash control could use special headers which would be difficult for the average user to ever figure out.
First and foremost you have to know what do you consider as OK to show photo . What is your authentication parameter. Like if user is allow to see the pic when is authenticated , check the same in , ashx page before allowing it to see. Because calling inside the html as src or putting the same in browser does not make any difference for server . So you need to check some validation in case user is not at all supposed to see in any way directly or in directly
Store the URL and parameter in Session state and access the Session in the HttpHandler. To do this you would need to implemement the IRequiresSessionState in your handler:
Problem with HttpHandler and session state
Getting Session State in HttpHandlers (ASHX files)
Related
I can get in one call /me details including picture, email, name.
But URL returned is of an extremely small picture (50px*50px).
I know I can make additional call to get bigger image with something like:
.../me/picture?width=999
But is it possible to combine it with:
https://graph.facebook.com/v2.5/me?fields=id,relationship_status,picture,email,gender,first_name,last_name,significant_other
to receive all this information in one request-response instead of two?
Here you go:
https://graph.facebook.com/v2.6/me?fields=id,relationship_status,picture.width(999),email,gender,first_name,last_name,significant_other
You can make nested requests by following this:
https://developers.facebook.com/docs/graph-api/using-graph-api#fieldexpansion
I've got a C#/ASP.net application. When a user searches for data using a few standard dropdowns and text boxes, I run a SQL query to grab all of the users search preferences and then auto-fill the controls based on what's returned. The user can then search using those presets, or change any of the choices and search again.
The problem is, this requires a call to the DB every time that search page is loaded. I was hoping there might be a way to grab all the preferences once when the user logs in the first time and then store them somehow, to lighten the load on my SQL Server db. Has anyone ever come across this issue and discovered an efficient way to handle it?
What about using the old goodies - Cookies?
HttpCookie aCookie = new HttpCookie("SearchPreferences");
aCookie.Values = /* your collection of preferences */;
aCookie.Expires = /* DateTime of expiration */;
Response.Cookies.Add(aCookie);
... or sessions you would destroy when an user logs out?
if (Session["SearchPreferences"] != null) {
/* loading the preferences */
} else {
/* preferences are already loaded */
}
You can also set their expiration using Session.TimeOut.
Edit:
As it may sound from the discussion below, both of these methods have their pros and cons. For that I've thought that adding a few more should give your opportunity to choose what suits you best.
System.Web.Caching.Cache seems like the most modern and fastest way of doing this.
Cache c = System.Web.Caching.Cache();
c.Add(key, value, dependencies, absoluteExpiration,
slidingExpiration, priority, onRemoveCallback);
However, there's still an option of ApplicationState, which is an object that can hold your values while the application is running.
If you're looking for client-side persistence, Cookies and Sessions (which still depend on cookies on the client, unless cookieless) is one option (see previous answer). You can also look into newer client side persistence options (where Web Storage has most browser support). Hth...
I have a session variable which is used to store a datatable (which changes depending on how the user wishes to add / remove items (data items in the datatable).
At the last page of the whole web application, I have a submit page to allow the user to submit the selected items in the datatable.
Because I think session variables may expire if the page is left open too long, and to prevent errors arising from expired variables, at the page_load function's !IsPostBack I assigned the session variable to a viewstate variable (so the data will be stored in the page's viewstate and not expire).
if(!IsPostBack){ ViewState["myDataTable"] = Session["myDataTable"]}
1) Is this the standard practice and are there any implications / errors when assigning a session variable to a viewstate?
2) After calling ViewState["myDataTable"] = Session["myDataTable"], is it ok to do Session["myDataTable"] = null ?
It really depends on the kind and size of data you have there.
It is key to remember that you need to treat anything you send to the client as compromised data. Another way to put it, if you'd be ok with an user having available a form that allows them to input every single bit of that data, only then it is ok.
All said, the viewstate is normally signed, but history as proven is a good idea to follow that general security advice.
As for the size, you need to keep an eye on the amount of data being exchanged on each request.
Last about clearing that session value afterwards, asp.net mvc does similar for what it calls TempData. The scenario for its use: pass some data from one page to the next on non post scenarios + and when you don't want it in the query string.
Yes, you can do it. but viewstate tends to slow the page loading due to extra overhead. If your dataset is small it is ok, but if its bigger then look for other alternatives.
How ever I will recommend not to go with this method[security problem,slow etc.], instead device a way so that session dosent expire if any page is open?? how?? use jquery/ajax to maintain a connection with server at regular interval.
If you want to go some further implement sql session. It will be the best.
Hope these info help you.
I stucked at a condition , where i need to share values between the pages. I want to share value from Codebehind via little or no javascript. I already have a question here on SO , but using JS. Still did'nt got any result so another approach i am asking.
So I want to know can i pass any .net object in query string. SO that i can unbox it on other end conveniently.
Update
Or is there any JavaScript approach, by passing it to windows modal dialog. or something like that.
What I am doing
What i was doing is that on my parent page load. I am extracting the properties from my class that has values fetched from db. and put it in a Session["mySession"]. Some thing like this.
Session["mySession"] = myClass.myStatus which is List<int>;
Now on one my event that checkbox click event from client side, i am opening a popup. and on its page load, extracting the list and filling the checkbox list on the child page.
Now from here user can modify its selection and close this page. Close is done via a button called save , on which i am iterating through the checked items and again sending it in Session["mySession"].
But the problem is here , when ever i again click on radio button to view the updated values , it displays the previous one. That is , If my total count of list is 3 from the db, and after modification it is 1. After reopening it still displays 3 instead of 1.
Yes, you could but you would have to serialize that value so that it could be encoded as a string. I think a much better approach would be to put the object in session rather than on the URL.
I would so something like this.
var stringNumbers = intNumbers.Select(i => i.ToString()).ToArray();
var qsValue = string.Join(",", stringNumbers);
Request.Redirect("Page.aspx?numbers=" + sqValue);
Keep in mind that if there are too many numbers the query string is not the best option. Also remember that anyone can see the query string so if this data needs to be secure do not use the query string. Keep in mind the suggestions of other posters.
Note
If you are using .NET 4 you can simplify the above code:
var qsValue = string.Join(",", intNumbers);
Make the object serializable and store it in an out-of-process session.
All pages on your web application will then be able to access the object.
you could serialize it and make it printable but you shouldn't
really, you shouldn't
The specification does not dictate a minimum or maximum URL length, but implementation varies by browser and version. For example, Internet Explorer does not support URLs that have more than 2083 characters.[6][7] There is no limit on the number of parameters in a URL; only the raw (as opposed to URL encoded) character length of the URL matters. Web servers may also impose limits on the length of the query string, depending on how the URL and query string is stored. If the URL is too long, the web server fails with the 414 Request-URI Too Long HTTP status code.
I would probably use a cookie to store the object.
Short question is : "How do I save current url into cookie file?"
And the whole problem is as follows. I have to save current filters that client have applied to my grid in his cookie, that next time he logs in the data looks just as he wants it to look like. The service doesn't have any "login" stuff, just provides available data to the user. This whole thing is written in ASP.MVC/C#.
If you have any other solutions to this task I will be happy to discuss them!
Thanks for giving a minute.
http://msdn.microsoft.com/en-us/library/ms178194.aspx
In short, you can access the user's cookie data by calling Response.Cookies to get a dictionary of HttpCookie objects keyed by the name you give each cookie (much like Session or ViewState data stores). You can add to this by specifying a cookie name in the indexer as if it were there and setting Value and ExpirationDate properties, or by creating a new HttpCookie and calling Cookies.Add.
It may not be necessary to store the whole URL, although a cookie can contain up to 4k of data. I would instead store the query string (which has the pertinent filter settings) under a unique name that that specific page will know to get its cookie data from ("<page name here>FilterSettings", perhaps). Then, on PreInit, get the Request, and if its QueryString is empty but there's a Cookie with saved filter settings, tack the saved query string onto the current url and redirect.
Remember that the client has control over whether to save cookie data; the browser may accept all, accept from trusted sources, ask on all, or refuse all. In this case, no big deal; it's pure convenience, which is exactly what a cookie should be used for. If this were valuable data, you may have had to persist it server-side based on the user.