In ASP.Net, is anyone aware of a way to bypass Forms Authentication if a specific query string parameter is passed in?
Such as:
mydomain.com/myprotectedpage.aspx
...I would like to be protected by Forms Authentication (and so, redirected to login page)
mydomain.com/myprotectedpage.aspx?myBypassParameter=me
...I would like the page to render as normal
Is this at all possible?
Not really any "official" way of doing it.
You could do what I do, is have a base page instead of system.web.ui.page like so:
Public MustInherit Class ProtectedPage
Inherits System.Web.UI.Page
Private Sub Page_InitComplete(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.InitComplete
If User.Identity.IsAuthenticated = False Then
If String.IsNullOrEmpty(Request.QueryString("myBypassParameter")) Then
FormsAuthentication.RedirectToLoginPage()
End If
End If
End Sub
End Class
In your code behind, you could simply use Request.QueryString["myBypassParameter"] and check its value. If it's an invalid value, then use FormsAuthentication.RedirectToLoginPage or a custom redirect to put the user back at the log in page. However, this doesn't seem like a secure method of protecting a page. What if someone got hold of the specific parameter and managed to gain access to your protected page? Also, you want to make sure that the QueryString value is valid (maybe by a regular expression) to ensure the user hasn't passed malicious code which will then be read by your application.
You might be able to jam some quick code into the Application_AuthenticateRequest event. You could then test for the parameter and adjust the User.Identity as necessary to allow the page. You'd have to put in a page check as well to make sure it didn't allow this behavior on all restricted pages.
I wouldn't recommend this design as an approach though. If you need to have a protected area accessed in an anonymous fashion, it'd be better to put all of your functionality into a UserControl and then use a protected/unprotected version of a parent page. This would allow you to control what goes out and when.
Related
For my webpages, I decided to create a reusable, external (that is, the code is a separate class outside of the page's own classes), class to deal with managing cookies in a certain fashion.
So in my class constructor, I did something like this:
private property cookiepageas Page
Public Sub New(whatpage as Page)
cookiepage= whatpage
End Sub
This allows me to pass the page context to my external class.
This way, I can get intellisense to allow me to do this:
private property cookie as httpcookie
cookie = cookiepage.Request.Cookies.Get(cookiename) 'get the current cookie
That compiles. The problem is that when I run it in the browser, I get this error:
Request is not available in this context
How, then, can I request the cookie from my external class?
(you can post vb or c# - I like both)
Ah, instead of passing the Page, I did this:
cookie = HttpContext.Current.Request.Cookies.Get(cookiename)
Is there an easy way to get forms authentication to ignore the returnURL?
So the user clicks a link, the site timesout, they get redirected to my login page (which appends ReturnUrl to the URL) - I don't want this to happen, or for it to be ignored when they login again.
You can strip it off if you don't want to show it. I do that because I don't want it to show with SEO-friendly URLs that I have setup.
In the Global.asax file put the following:
Protected Sub Application_EndRequest(sender As Object, e As System.EventArgs)
Dim redirectUrl As String = Me.Response.RedirectLocation
If Not Me.Request.RawUrl.Contains("ReturnUrl=") AndAlso Not String.IsNullOrEmpty(redirectUrl) Then
Me.Response.RedirectLocation = Regex.Replace(redirectUrl, "\?ReturnUrl=(?'url'[^&]*)", String.Empty)
End If
End Sub
One option is to have some code in your login form's code-behind that does the following:
if (!string.IsNullOrEmpty(Request.QueryString["returnUrl"]))
{
Response.Redirect("path/to/my/login.aspx");
}
In other words, check in your login page for the presence of the returnUrl querystring parameter and if it's present, strip it out by redirecting back to yourself.
I don't think you can prevent this from being tacked onto the URL when using Forms Authentication.
However, you don't need to call RedirectFromLoginPage (which is what I'll presume you're doing at the minute); what you can do is simply use SetAuthCookie to persist the login state and Response.Redirect anywhere you like after that.
I'm new to web development, and I'm currently using ASP.net. I wonder what would I need to do to let the browser wait for 3 seconds so my users can read the text "Customer Successfully Added" before turning to another page? I have attached my code as follows.
Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAdd.Click
Dim db As New DatabaseClass
db.addProfile(txtLN.Text, txtFN.Text, txtUsername.Text, txtPassword.Text, txtAddress.Text, txtZip.Text, txtPhone.Text, txtEmail.Text)
lblMessage.Text = "Customer Successfully Added"
End Sub
In addition, I'm not sure how to utilize MSDN. For me, its information overload, I'm wondering how to go about finding the solution on MSDN so i would be able to solve my problems in the future. Thank you!
You can't do it in the code behind of the page because of how asp.net works - the label text would not update until after the timeout occurred if you did it in the code-behind.
The server-side processing spits all the html back to the browser only after it has completely processed any server-side code unless you're using Ajax. Since you're new, I won't even bother going into how to do it with Ajax as there is a MUCH simpler option for accomplishing what you want.
A simple method to accomplish what you're looking for would be to have a simple HTML page that just has a message that says "Customer successfully added" and use javascript (client-side code) to pause and then redirect using the Javascript "SetTimeout" function.
There's an example here: http://www.bloggingdeveloper.com/post/JavaScript-Url-Redirect-with-Delay.aspx
The logic flow wshould work like this:
The original page should add the record (in code-behind) then redirect to this simple html page (in code-behind). The html page should have the "Customer Added" message and use the SetTimeout and Redirect to go to whatever page you want the user to see after viewing the message.
For stuff like this you need the code to run client side rather than on the server. The easiest way to do this is to return some javascript with your page (in the .aspx part rather than the code behind)
Take a look here for an idea of what to do :)
The page is displayed for a few seconds and then the javascript triggers a redirect to a url of your choosing. Just add something like this into your html.
You can emit javascript to redirect to the other page, using the setTimeout function.
This is best accomplished using the ScriptManager to register any javascript on the page.
I'm using a custom control in ASP.NET that handles file uploading for me. The control has a handler in the code-behind using something like this:
Protected Sub UploadFileComplete(ByVal sender As Object, ByVal e As UploadControl.FileUploadCompleteEventArgs) Handles UploadControl.FileUploadComplete
Within that sub, I post back to the server and do some work on the database, but then when I come back, I want JavaScript to register at that point.
However, when I use Page.ClientScript.RegisterClientScriptBlock or ScriptManager.RegisterClientScriptBlock, the scripts don't load on the page. I need this JavaScript to run and update the page, and to close the upload dialog window. I assume it's because the page is already loaded.
Does anyone have any good ideas on how to do this?
Alright so turns out it's like this...
On the server side (code-behind), in the UploadFileComplete() sub, you can access that EventArgs variable by using the method e.CallbackData = [WHATEVER].
And then in your javascript, you use this built in client function:
function UploadComplete(args){
alert(args.callbackData);
}
And that args.callbackData variable has whatever you put in via server side. Pretty slick I think! But hard to figure out cause they didn't have it documented very well.
This way, you don't need to add your own RegisterClientScriptBlock method, because you can pass in anything you want to JavaScript using their built in method.
I trying to implement a typical languages menu where users can select the language they want to view the site in through a menu that appears throughout all pages in the site.
The menu will appear on multiple master pages (currently one for pages where users are logged in and one for pages where users are not).
My current implementation is having a single master page base class (let's call it MasterBase). MasterBase has an event
public event LanguageChangedEventHandler LanguageChanged;
where LanguagedChangedEventHandler is simply defined as
public delegate void LanguageChangedEventHandler(string NewCulture);
MasterBase also has an overridable method
protected virtual void OnLanguageChanged(string NewCulture)
which just basically fires the event.
Each master page that inherits MasterBase overrides OnLanguageChanged and does the usual stuff like set the Thread's CurrentUICulture and the language cookie then does a
Server.Transfer(this.Page.AppRelativeVirtualPath, true);
to get the page to reload with localized values for the new culture. On the master page for logged in users it also updates the user's language pref in the db.
Each language option is currently a LinkButton on a master page that inherits from MasterBase. When the link is clicked it calls the base OnLanguagedChanged method passing in the correct culture info. E.g.
protected void btnEnglish_Click(object sender, EventArgs e) {
this.OnLanguageChanged("en-US");
}
Each page that needs to handle a language change then has some code in the page load that looks like...
((MasterBase)this.Master).LanguageChanged += this.Page_OnLanguageChanged;
// Where Page_OnLanguageChanged has the signature of LanguageChangedEventHandler
// and has stuff like reloading options in a drop down using the new language.
Quite a convoluted 'framework' =)
Firstly it's hard for new developers to know they have to hook up a method to the MasterBase's LanguageChanged event to handle language changes. Yes, we do document it. But still it's not something straightforward and obvious.
Secondly, all language changes are post backs. This is problematic especially when you want to navigate back with the browser Back button.
I'm looking for a more elegant solution. One that doesn't have both the problems above and also handles my current requirements.
Greatly appreciate any suggestions. Thanks.
It seems to me that it would be better to implement this in a control that sets an application variable that all pages could use. That way you could just implement the code in one place and have it always available on each page that displays the control (could be in your master's so all pages that inherit get it automatically). I think in the control you would have a handler that sets the global language setting and then reloads the page. Each page would check the language setting during page_load or prerender and load the proper localized strings accordingly.
I would just use the PreInit event on base page to set the current ui culture. I am not clear on why you would need each page to know when language is changed.