ASP.net Forms Identity Authentication Detailed _ practical skills

Source: Internet
Author: User
Tags decrypt http request httpcontext send cookies ticket

Asp. NET Identity Authentication Basics

Before starting today's content, I think there are two most fundamental questions to be clear first:

1. How can I tell if the current request was initiated by a logged-on user?

2. How do I get the login name of the currently logged-on user?

In the standard ASP.net authentication method, the answers to the top two questions are:

1. If request.isauthenticated is true, it means that it is a logged-on user.

2. If it is a logged-on user, Access HttpContext.User.Identity.Name can obtain the login name (both instance properties).

Next, this article will expand around the top two questions, please read on.

Asp. NET identity authentication process

In ASP.net, the whole process of identity authentication can be divided into two stages: Authentication and authorization.

1. Certification phase: Identify the user who is currently requesting is a recognized (logged on) user.

2. Authorization phase: Whether the current request is allowed to access the specified resource.

These two phases are represented by AuthenticateRequest and authorizerequest events in the ASP.net pipeline.

In the certification phase, ASP. NET examines the current request and attempts to construct the HttpContext.User object for use in subsequent processing, based on the authentication method set by Web.config. During the authorization phase, the resources accessed by the current request are checked for access, because some protected page resources may require specific users or groups of users to access. Therefore, even a logged-on user may not be able to access certain pages. When a user is found unable to access a page resource, ASP. NET redirects the request to the login page.

Protected page and login page can be specified in the Web.config, the specific method can refer to the following text.

In ASP.net, forms authentication is implemented by FormsAuthenticationModule, and the authorization check for URLs is implemented by UrlAuthorizationModule.

How to implement login and logoff

I described earlier that you can use request.isauthenticated to determine whether the current user is a logged-on user, so how is this process achieved?

To answer this question, I prepared a simple sample page with the following code:

<fieldset><legend> User status </legend><form action= "<%= request.rawurl%>" method= "POST" > 
 <% if (request.isauthenticated) {%> 
  the current user is logged in, login name: <%= Context.User.Identity.Name.HtmlEncode ()%> <br/>    
  <input type= "Submit" Name= "logon" value= "Exit"/> 
 <%} else {%> 
  <b> Current user is not logged in yet. </b> 
 <%}%>    
</form></fieldset> 

The page displays the following effect:

Based on the previous code, I think it's right to see this page now, yes, I'm not logged in yet (I haven't implemented this feature yet).

Next I add some code to achieve user login. Page code:

<fieldset><legend> Normal login </legend><form action= "<%= request.rawurl%>" method= "POST" > 
 Login Name: <input type= "text" name= "LoginName" style= "width:200px" value= "Fish"/> <input " 
 submit" Name= "Normallogin" value= "login"/> 
</form></fieldset> 

Now the page display effect:

Implementation code for login and exit login:

public void Logon () 
{ 
 formsauthentication.signout (); 
} 
 
public void Normallogin () 
{ 
 //----------------------------------------------------------------- 
 / /Note: Demo code for simplicity, this does not check to see if the username and password are correct. 
 //----------------------------------------------------------------- 
 
 string loginName = request.form[" LoginName "]; 
 if (string. IsNullOrEmpty (LoginName)) return 
  ; 
  
 Formsauthentication.setauthcookie (LoginName, true); 
 
 Tryredirect (); 
} 

Now, I can try the login function. After clicking the login button, the page appears as follows:

As you can see from the picture's display, the Normallogin () method I wrote earlier does enable you to log in.
Of course, I can also click the Exit button at this time, and then go back to the display of picture 2.

Writing here, I think it is necessary to summarize the way to implement login and logoff in asp.net:

1. Login: Call the Formsauthentication.setauthcookie () method, passing a login name.

2. Logout: Invoke the FormsAuthentication.SignOut () method.

Protect restricted pages

In a asp.net web site, some pages allow access to all users, including some users who are not logged on, but some must be logged on and some pages may require specific users or members of the user group to access them. Such pages can also be called "Restricted pages," which generally represent more important pages and contain important operations or functions.

To protect restricted access to a page, ASP. NET provides an easy way to specify which users or user groups (roles) are allowed access to restricted resources in Web.config, or to prohibit access.

For example, the site has a page: myinfo.aspx, it requires that visitors to this page must be a logged-on user, you can configure this in Web.config:

<location path= "myinfo.aspx" > 
 <system.web> 
  <authorization> 
   <deny users= "?" /> 
  </authorization> 
 </system.web> 
</location> 

For convenience, I might place several admin-related pages in the admin directory, which are obviously only allowed to be accessed by members of the Admin user group. For this scenario, we can set access rules directly against a directory:

<location path= "admin" > 
 <system.web> 
  <authorization> 
   <allow roles= "admin" > 
   <deny users= "*"/> 
  </authorization> 
 </system.web> 
</location> 

This eliminates the need for a single page to be set up, and you can create a web.config in the directory to specify access rules for the directory, refer to the following example.

In the previous example, one thing to pay special attention to is:

1. The order between allow and deny must not be written incorrectly, UrlAuthorizationModule will be judged in this order.

2. If a resource is allowed to access only one type of user, the last rule must be <deny users= "*"/>

In the configuration of allow and deny, we can specify multiple users in a single rule:

1. Using the Users property, the value is a comma-delimited list of user names.

2. Using the Roles property, the value is a comma-delimited list of roles.

3. The question mark (?) represents an anonymous user.

4. An asterisk (*) indicates all users.

Issues where the login page does not display correctly

Sometimes, we may want to develop an internally used Web site program that requires no anonymous user access, that is, all users must log in before they can access them. Therefore, we typically set this in the web.config in the root directory of the site:

<authorization> 
 <deny users= "?" /> 

For our example, we can also set this. When you open the page in the browser, the rendering effect is as follows:

As you can see from the picture: The style of the page is not displayed correctly, and there is a line of text at the bottom.

The complete code for this page is this (it references a CSS file and a JS file):

&lt;%@ Page language= "C #" codefile= "Default.aspx.cs" inherits= "_default"%&gt; &lt;html xmlns= "http://www.w3.org/1999 /xhtml "&gt; &lt;head&gt; &lt;title&gt;formsauthentication demo-http://www.cnblogs.com/fish-li/&lt;/title&gt; &lt;l Ink type= "text/css" rel= "Stylesheet" href= "Css/stylesheet.css"/&gt; &lt;/head&gt; &lt;body&gt; &lt;fieldset&gt;&lt;l egend&gt; Normal login &lt;/legend&gt;&lt;form action= "&lt;%= request.rawurl%&gt;" method= "POST" &gt; Login: &lt;input type= "text 
 "Name=" LoginName "style=" width:200px "value=" Fish "/&gt; &lt;input" type= "" Submit "Name=" Normallogin "value=" Login "/&gt; &lt;/form&gt;&lt;/fieldset&gt; &lt;fieldset&gt;&lt;legend&gt; User status &lt;/legend&gt;&lt;form action= "&lt;%= REQUEST.R Awurl%&gt; "method=" Post &gt; &lt;% if (request.isauthenticated) {%&gt; The current user is logged in, logon name: &lt;%= Context.User.Identity . Name.htmlencode ()%&gt; &lt;br/&gt; &lt;% var user = Context.User as myformsprincipal&lt;userinfo&gt;; %&gt; &lt;% if (user!= null) {%&gt; &lt;%= user. Userdata.tostring (). HtmlEncode ()%&gt; &lt;%}%&gt; &lt;input type= "Submit" Name= "Logon" value= "Exit"/&gt; &lt;%} else {%&gt 
   ; &lt;b&gt; the current user is not logged in yet. &lt;/b&gt; &lt;%}%&gt; &lt;/form&gt;&lt;/fieldset&gt; &lt;p id= "HideText" &gt;&lt;i&gt; text that should not be displayed &LT;/I&GT;&L  t;/p&gt; &lt;script type= "Text/javascript" src= "js/jscript.js" &gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt;

The last line of text on the page doesn't usually appear because the following code is in the Jscript.js:

 
 

This JS code can do what, I think will not have to explain. Although this JS code is not valuable, but I mainly want to demonstrate in the login page reference JS scene.

According to the previous picture, we can guess: CSS and JS files are not properly loaded. To confirm that this is the case, we can open Firebug and take a look at the page load:

According to the clues provided by Firebug we can analyze the page in the access to CSS, JS file, is actually redirected to the login page, so the results are certainly meaningless, so it caused the login page is not correct.

Do you remember the "authorization"?
Yes, now it's because we set up the Web.config to not allow anonymous user access, so all resources do not allow anonymous users to access, including the login page refers to the CSS, JS files. When the authorization check fails, the request is redirected to the login page. Therefore, the login page itself refers to the CSS, JS file finally received the response content is actually a login page HTML code, resulting in them can not play a role, performance for the login page style display is incorrect, and the reference JS file also does not work.

However, one thing is strange: why is there no redirection when accessing the login page?

The reason is this: within ASP.net, when the discovery is to access the login surface, set httpcontext.skipauthorization = True (in fact, an internal call), such settings will tell the following authorization check module: Skip the authorization check for this request. Therefore, the login page always allows all users to access, but the CSS file and the JS file are in the other request, those requests do not want to skip the authorization module check.

In order to solve the problem that the login page does not display correctly, we can handle this:

1. In the Web site root directory in the web.config to set the login page referenced js, CSS files are allowed anonymous access.

2. You can also directly target JS, the CSS directory is set to allow anonymous users to access.

3. You can also create a Web.config file in CSS, JS directory to configure the corresponding directory authorization rules. Refer to the following Web.config files:

<?xml version= "1.0"?> 
<configuration> 
 <system.web> 
  <authorization> 
   < Allow users= "*"/> 
  </authorization> 
 </system.web> 
</configuration> 

The third approach is to not modify the Web.config files in the root directory of the Web site.

Note: What you see in IIS is not the same as the results you see in Visual Studio. because, like JS, CSS, image such files belong to static resource files, IIS can directly handle, do not need to give asp.net to respond, so there will be no authorization check failed, so, if such sites deployed in IIS, see the results are normal.

Understanding Forms Identity Authentication

Earlier I demonstrated how to use code to implement the process of login and logoff, and then look at the login, ASP. NET what does it do, how does it know that the current request is a logged-on user?

Before continuing to explore this issue, I think it is necessary to understand some of the features of the HTTP protocol.

HTTP is a stateless protocol, and stateless means that the Web server, when processing all incoming requests, simply does not know whether a request is a user's first request and subsequent request, or another user's request. Each time the Web server processes the request, it executes it from start to finish, according to the processing code of the resource that the user accesses, and then outputs the response content, and the Web server simply does not remember which user's request has been processed, so we usually say the HTTP protocol is stateless.

Although the HTTP protocol is stateless with the Web server, our business needs are stateful, typically a user login, in which the Web server is required to distinguish whether a request was initiated by a logged-on user or by which user the current request originated. When developing Web applications, we usually use cookies to save some simple data for the server to maintain the necessary state. Since this is a common practice, let's take a look at the cookie usage of the page now, here's a list of cookies I've seen with Firefox:

The name: Logincookiename, which I specified in the web.config:

<authentication mode= "Forms" > 
 <forms cookieless= "usecookies" name= "Logincookiename" loginurl= "~/" Default.aspx "></forms> 
</authentication> 

In this configuration, I specify not only the cookie name for the login status, but also the authentication mode and how the cookie is used.

To determine if this cookie is related to login status, we can delete it in the interface provided by the browser, and then refresh the page, the page will display the following effect:

At this point, the page shows that the current user is not logged in.

To confirm that this cookie is related to the login status, we can log in again and then log out.
Find that the cookie does not exist as long as the page shows that the current user is not logged in.

In fact, by SetAuthCookie This method name, we can also guess that this operation will write a cookie.
Note: Forms logins without Cookie mode are not discussed in this article.

We can see from the previous screenshot that although the current username is Fish, the value of the cookie is a string of garbled strings.
Because of security considerations, ASP. NET has been encrypted with cookies, which prevents a malicious user from constructing a cookie to bypass the login mechanism to impersonate a logged-on user. If you want to know how this string of encrypted strings is obtained, please refer to the following text.

Summary:

1. Forms identity authentication is specified in Web.config and we can also set other configuration parameters for forms authentication.

2. Forms-Authenticated login status is maintained through cookies.

3. Forms-Authenticated login cookies are encrypted.

Understanding Forms Identity Authentication

After the previous cookie analysis, we can see that the value of the cookie is a string of encrypted strings, and now we're going to analyze the encryption process and the cookie's role in identity authentication.

The logon operation usually checks the user's supplied user name and password, so the login status must also be secure enough. In forms authentication, because the login status is stored in a cookie and the cookie is saved to the client, the ASP, in order to ensure that the login status is not spoofed by a malicious user. NET uses the encrypted way to save the login state. To achieve security, ASP. NET uses "Forms authentication Credentials" (that is, the FormsAuthenticationTicket object) to represent a forms logged-on user, and encryption and decryption are implemented by FormsAuthentication's encrypt and decrypt methods.

The user logon process is roughly the same:

1. Check the user's submitted login name and password is correct.

2. Create a FormsAuthenticationTicket object based on the login name.

3. Call Formsauthentication.encrypt () encryption.

4. Create a login cookie based on the result of the encryption and write to response.

After the logon verification is complete, a redirection operation is typically generated, and each subsequent request will bring the previously generated encryption cookie for the server to verify the logon status for each request.

The (authentication) process for each request is as follows:

1. FormsAuthenticationModule attempts to read the login cookie.

2. Parse out the FormsAuthenticationTicket object from the cookie. Expired objects will be ignored.

3. Construct the FormsIdentity object based on the FormsAuthenticationTicket object and set the Httpcontext.usre

4. UrlAuthorizationModule perform authorization checks.

In the implementation of login and authentication, FormsAuthenticationTicket and FormsAuthentication are two core types, which can be considered as a data structure, which can be considered as a tool class to deal with the former.

UrlAuthorizationModule is an authorization checking module, in fact it is more independent of the login authentication, so if we do not use this authorization check based on user name and user group, we can also disable this module.

Because the cookie itself has an expiration feature, FormsAuthenticationTicket also supports expiration policies for security purposes, however, ASP. NET's default settings support FormsAuthenticationTicket's adjustable expiration behavior, which is: Slidingexpiration=true. When either of these are expired, the login status is invalidated.

The main judgment logic of FormsAuthenticationTicket's adjustable expiration is implemented by the Formsauthentication.renewticketifold method, the code is as follows:

public static FormsAuthenticationTicket Renewticketifold (FormsAuthenticationTicket told) 
{ 
 // This code means that the FormsAuthenticationTicket object will be updated when the specified timeout period passes largely. 
 
 if (told = null) return 
  null; 
  
 DateTime now = DateTime.Now; 
 TimeSpan span = (TimeSpan) (now-told.issuedate); 
 TimeSpan span2 = (TimeSpan) (Told.expiration-now); 
 if (Span2 > span) return 
  told; 
  
 Return to New FormsAuthenticationTicket (Told.version, Told.name, now 
  , now + (told.expiration-told.issuedate), 
  told.ispersistent, Told.userdata, Told.cookiepath); 
Request.isauthenticated can tell us if the current request has been authenticated, let's take a look at how this property is implemented: public

bool isauthenticated 
{get 
 {return (( 
  this._context. User!= null) 
   && (This._context. User.Identity!= null)) 
   && This._context. User.Identity.IsAuthenticated); 
 } 

As you can see from the code, its return result is basically based on the judgment of Context.User.
In addition, because both user and identity are properties of two interface types, different implementations have an effect on the return value.

Because this instance property of HttpContext.User may be used frequently, in order for it to work properly, Defaultauthenticationmodule checks whether this property is null in the Postauthenticaterequest event of the ASP.net pipeline, and if it is null,defaultauthenticationmodule gives it a default GenericPrincipal object that indicates a user who is not logged on.

I think the very core of ASP.net's identity authentication is actually the object that httpcontext.user this attribute points to. To better understand forms authentication, I think it would be helpful to implement the interface of the user object again.

Implementing a custom Identity authentication identity

The simplest way to implement the ASP.net forms authentication is shown earlier, which is to call the SetAuthCookie method directly. However, this method can be invoked with only one login name passed. However, sometimes additional information related to the login needs to be saved in order to facilitate subsequent request processing. Although you know ASP.net uses cookies to save login status information, we can also directly save the additional information mentioned above directly in the cookie, but consider the security, we also need to design some encryption methods, but also need to consider where the additional information saved for easy to use, and also consider with login and logoff synchronous repair Change. So it's a bit tedious to implement these operations.

In order to save the additional user information associated with the login, I think implementing a custom Identity authentication identification (HttpContext.User instance) is an easy workaround.
Understanding this approach will also give us a clearer idea of forms identity authentication.

The core of this approach is (divided into two sub processes):

1. When you log on, create a custom FormsAuthenticationTicket object that contains the user information.

2. Encrypt the FormsAuthenticationTicket object.

3. Create a login cookie that will contain the results of the FormsAuthenticationTicket object's encryption.

4. In the early stages of the pipeline, read the login cookie and, if so, decrypt it.

5. Restore the user information we saved from the decrypted FormsAuthenticationTicket object.

6. Set HttpContext.User for our custom object.

Now, let's take a look at the definition of the HttpContext.User attribute:

Gets or sets security information for the current HTTP request. //// 
Returns the result: 
//  security information for the current HTTP request. 

Since this property is just an interface type, we can also implement this interface ourselves.

Consider better versatility: Different projects may require different types of user information to be accepted. So, I've defined a generic class.

public class myformsprincipal<tuserdata>: IPrincipal 
 where Tuserdata:class, new () 
{ 
 private IIdentity _identity; 
 Private Tuserdata _userdata; 
 
 Public Myformsprincipal (FormsAuthenticationTicket ticket, Tuserdata userData) 
 { 
  if (ticket = null) 
   throw New ArgumentNullException ("Ticket"); 
  if (UserData = = null) 
   throw new ArgumentNullException ("UserData"); 
 
  _identity = new FormsIdentity (ticket); 
  _userdata = UserData; 
 } 
  
 Public Tuserdata UserData 
 {get 
  {return _userdata}} 
 
 Public IIdentity Identity 
 {get 
  {return _identity}} 
 } 
 
 public bool IsInRole (string role) 
 { 
  //To determine the operation of the user group is left to UserData to implement. 
 
  IPrincipal principal = _userdata as IPrincipal; 
  if (principal = null) 
   throw new NotImplementedException (); 
  else return 
   principal. IsInRole (role); 
 } 

The type of user information that is used with it is defined as follows (which can be defined according to the actual situation):

public class Userinfo:iprincipal 
{public 
 int UserId; 
 public int GroupId; 
 public string UserName; 
  
 If you have additional user information, you can continue to add it. Public 
 
 override String ToString () 
 {return 
  string. Format ("UserId: {0}, GroupId: {1}, UserName: {2}, ISAdmin: {3}", 
   UserId, GroupId, UserName, IsInRole ("Admin")); 
 } 
 
 #region IPrincipal members 
 
 [Scriptignore] public 
 iidentity Identity 
 {get 
  {throw new NotImplementedException (); Public 
 
 bool IsInRole (string role) 
 { 
  if (string). Compare (role, "Admin", true) = = 0) return 
   GroupId = = 1; 
  else return 
   GroupId > 0; 
 } 
 
 #endregion 

Note: The type of user information is not required to implement the IPrincipal interface, if you do not need the user group's judgment, you can not implement this interface.

method to call when logging on (defined in Myformsprincipal type):

&lt;summary&gt;///Perform user login operation///&lt;/summary&gt;///&lt;param name= "loginName" &gt; Login &lt;/param&gt;///&lt;par Am Name= "UserData" &gt; User information related to login &lt;/param&gt;///&lt;param name= "expiration" &gt; Logon cookie Expiration time in minutes. &lt;/param&gt; public static void Signin (String loginName, tuserdata userData, int expiration) {if (string). 
 IsNullOrEmpty (LoginName)) throw new ArgumentNullException ("LoginName"); 
 
 if (UserData = = null) throw new ArgumentNullException ("UserData"); 1. 
 Turn the user data you want to save into a string. 
 string data = null; if (userData!= null) data = (new JavaScriptSerializer ()). 
 
 
 Serialize (UserData); 2. 
 Create a FormsAuthenticationTicket that contains the login name and additional user data.  FormsAuthenticationTicket ticket = new FormsAuthenticationTicket (2, LoginName, DateTime.Now, DateTime.Now.AddDays (1), 
 
 
 True, data); 3. 
 Encrypt the ticket and turn it into an encrypted string. 
 
 
 String cookievalue = Formsauthentication.encrypt (ticket); 4. Create a login cookie based on the result of the encryption HttpCookie cookie = new HttpCookie (formsauthentication.foRmscookiename, Cookievalue); Cookie. 
 HttpOnly = true; Cookie. 
 Secure = Formsauthentication.requiressl; Cookie. 
 Domain = Formsauthentication.cookiedomain; Cookie. 
 Path = Formsauthentication.formscookiepath; if (Expiration &gt; 0) cookie. 
 
 Expires = DateTime.Now.AddMinutes (expiration); 
 HttpContext context = HttpContext.Current; 
 
 if (context = = null) throw new InvalidOperationException (); 5. Write login Cookie context. Response.Cookies.Remove (cookies. 
 Name); Context. 
RESPONSE.COOKIES.ADD (cookie); 
 }

There is a need to add that there is an expiration limit on the login status. Cookies are valid and FormsAuthenticationTicket objects are valid. When either of these are expired, the login status is invalidated. By default, FormsAuthenticationModule will use the Slidingexpiration=true policy to handle FormsAuthenticationTicket expiration issues.

Login Page Code:

<fieldset><legend> Custom Login with user information </legend> <form action= "<%= request.rawurl%>" method= " Post "> 
 <table border=" 0 "> 
 <tr><td> Login name:</td> 
  <td><input type=" Text "Name=" LoginName "style=" width:200px "value=" Fish "/></td></tr> 
 <tr><td> userid:</td> 
  <td><input type= "text" name= "UserId" style= "width:200px" value= "The/></td" ></tr> 
 <tr><td>GroupId:</td> 
  <td><input type= "text" Name= "GroupId" style= "width:200px"/> 
  1 represents the administrator user 
  </td></tr> 
 <tr><td> user full name:</td> 
  <td><input type= "text" name= "UserName" style= "width:200px" value= "Fish Li"/></td></tr > 
 </table>  
 <input type= "Submit" Name= "Customizelogin" value= "login"/> 
</form> </fieldset> 

Login Processing Code:

public void Customizelogin () 
{ 
 //----------------------------------------------------------------- 
 / /Note: Demo code for simplicity, this does not check to see if the username and password are correct. 
 //----------------------------------------------------------------- 
 
 string loginName = request.form[" LoginName "]; 
 if (string. IsNullOrEmpty (LoginName)) return 
  ; 
 
 
 UserInfo UserInfo = new UserInfo (); 
 Int. TryParse (request.form["UserId"), out userinfo. USERID); 
 Int. TryParse (request.form["GroupId"), out userinfo. GROUPID); 
 UserInfo. UserName = request.form["UserName"]; 
 
 Login status valid MYFORMSPRINCIPAL<USERINFO> within 100 minutes 
 ;. Signin (LoginName, userinfo, MB); 
 
 Tryredirect (); 
} 

Page code to display user information:

<fieldset><legend> User status </legend><form action= "<%= request.rawurl%>" method= "POST" > 
 <% if (request.isauthenticated) {%> 
  the current user is logged in, login name: <%= Context.User.Identity.Name.HtmlEncode ()%> <br/> 
   
  <% var user = Context.User as myformsprincipal<userinfo>;%> 
  -if (user <% null) {% > 
   <%= user. Userdata.tostring (). HtmlEncode ()%> 
  <%}%> 
   
  <input type= "Submit" Name= "Logon" value= "Exit"/> 
 <%} else {%>
   <b> the current user is not logged in yet. </b> 
 <%}%>    
</form></fieldset> 

In order for the above page code to work, you must reset the HttpContext.User object before the page is displayed.
To do this, I added an event handler to the Global.asax:

protected void Application_AuthenticateRequest (object sender, EventArgs e) {HttpApplication app = (HttpApplication) se 
 NDEr; Myformsprincipal&lt;userinfo&gt;. Trysetuserinfo (app. 
context); Implementation code for Trysetuserinfo:///&lt;summary&gt;///Set user identity object based on HttpContext object///&lt;/summary&gt;///&lt;param name= "Conte XT "&gt;&lt;/param&gt; public static void Trysetuserinfo (HttpContext context) {if (context = null) throw new Argu 
 
 Mentnullexception ("context"); 1. Read Login Cookie HttpCookie cookie = context. 
 Request.cookies[formsauthentication.formscookiename]; if (cookie = = NULL | | string. IsNullOrEmpty (cookies. 
  
 Value)) return; 
  try {tuserdata userData = null; 2. Decrypts the cookie value, gets the FormsAuthenticationTicket object FormsAuthenticationTicket ticket = Formsauthentication.decrypt (cookie). 
 
  Value); if (Ticket!= null &amp;&amp; string. IsNullOrEmpty (ticket. UserData) = = False)//3. Restore User Data UserData = (new JavaScriptSerializer ()). Deserialize&lt;tuserdata&gt; (ticket. UserDATA); if (ticket!= null &amp;&amp; userData!= NULL)//4. Construct our Myformsprincipal instance and give the context again. 
   The user is assigned a value. Context. 
 User = new Myformsprincipal&lt;tuserdata&gt; (ticket, userData); The catch {/* has exceptions also do not throw, preventing attackers from probing.  */ } 
}

Use forms authentication between multiple servers

By default, ASP.net generates an accompanying secret key and stores it in the Local Security Authority (LSA). Therefore, when you need to use forms authentication between multiple machines, you can no longer use the method of randomly generating the key, which requires us to manually specify that each machine's key is consistent.

The key used for forms authentication can be specified in the Web.config machinekey configuration section, and we can specify the encryption decryption algorithm:

<machinekey 
 decryption= "Auto" [Auto | DES | 3DES | AES] 
 decryptionkey= "Autogenerate,isolateapps" [String] 
/> 

For these two properties, MSDN explains:

accessing restricted pages in the client program
This section is for all friends who are interested in automated testing.

Sometimes we need to use code to access certain pages, such as: we want to test the response of the server with code.

If it is a simple page, or the page allows all clients to access it, this will not be a problem, but if the page we are going to visit is a restricted page, then it must be the same as manual operation: first visit the login page, submit the login data, get the server generated login cookie, You will then be able to access other restricted pages (but with a login cookie).

Note: Because the logon cookie is usually encrypted and changes, it is difficult to maintain the code by hard-coded the login cookie directly in the code.

In the previous example, I have set up the web.config for myinfo.aspx to disallow anonymous access, if I use the following code to invoke:

private static readonly string myinfopageurl = "http://localhost:51855/MyInfo.aspx"; 
 
static void Main (string[] args) 
{ 
 //The result of this call is actually the output of the Default.aspx page, not myinfo.aspx 
 HttpWebRequest request = Myhttpclient.createhttpwebrequest (myinfopageurl); 
 String html = myhttpclient.getresponsetext (request); 
 
 if (HTML. IndexOf ("<span>Fish</span>") > 0) 
  Console.WriteLine ("Call succeeded.") "); 
 Else 
  Console.WriteLine ("Page results do not match expectations.") "); 
} 

At this point, the result of the output will be:

The page results do not match expectations.

If I use the following code:

private static readonly string loginurl = "http://localhost:51855/default.aspx"; 
private static readonly string myinfopageurl = "http://localhost:51855/MyInfo.aspx"; 
 
static void Main (string[] args) 
{ 
 //Create a Cookiecontainer instance for sharing cookies between multiple requests 
 Cookiecontainer Cookiecontainer = new Cookiecontainer (); 
 
 First go to login page login 
 myhttpclient.httppost (loginurl, "Normallogin=aa&loginname=fish", Cookiecontainer); 
 
 At this point, Cookiecontainer already contains the server-generated login cookie 
 
 //And then accesses the page to be requested. 
 string html = Myhttpclient.httpget (Myinfopageurl, cookiecontainer); 
 
 if (HTML. IndexOf ("<span>Fish</span>") > 0) 
  Console.WriteLine ("Call succeeded.") "); 
 Else 
  Console.WriteLine ("Page results do not match expectations.") "); 
 
 If you also want to access other restricted pages, you can continue to call. 
} 

At this point, the result of the output will be:

The call succeeded.

Description: In the improved version, I first create a Cookiecontainer instance that receives the cookie generated by the server during the HTTP call and sends the saved cookie to the service side when the HTTP request is sent. Once you have created the Cookiecontainer instance, each time you use the HttpWebRequest object, you assign the Cookiecontainer instance to the Cookiecontainer property of the HttpWebRequest object. Can be implemented in a number of HTTP calls to receive and send cookies, the end can simulate the browser cookie processing behavior, the server can also correctly identify the identity of customers.

asp.net forms authentication here, if you are interested in asp.net Windows authentication, please continue to focus on the relevant articles.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.