asp.net
basic architecture of the system
Let's assume that a system contains three separate Web sites for service customer Service center, shop online shopping center and Office Online Office Center. Service manages customer information, login and logoff procedures. The system will go to the login interface regardless of the client's access to any page of system, and the system automatically transfers to the customer's last requested page after the user logs in. And users can switch seamlessly in system thereafter. You do not need to log on again. That is, the single sign-on SSO is implemented in System Sign-On.
We know that the immediate state of a user is usually the use of application, session, cookies, and storage. These are not accessible across sites in the program. We need to communicate with each other through the site to confirm the user's immediate status.
Simple to implement
As shown in the figure, this diagram describes the process that the user accesses the system.
The first step is to assume that the user has visited any of the pages of the shop or office. The site on which the page is located will check the user's immediate status. If the user is already logged in, the information for any page is returned to the user. If the user is not logged in, it is automatically transferred to the validate page of the service to verify the user's service status. The shop or office requests the service to return the user's immediate status.
In the second step, validate verifies the user's immediate state and, if the user is already logged in, the service returns the user's immediate status to the shop or Office synchronization page synchronous, notifying the shop or office of synchronizing user status. If the user is not logged in, it automatically turns to the customer page and prompts the user to log in.
The third step, the user completes the login process, when the user successfully logs on, automatically reverts to the Validate page, informs the shop or the office synchronous to carry on the user state synchronization.
Fourth step, after the user state synchronization completes, at the local site, the user status becomes online state, can access any page.
In the process above. We know that no matter which site users visit, users need only one login, to ensure that users in the immediate state of the service is online, no longer need to do a second logon process.
Now that our thinking is clear, the concrete implementation we will complete in the Code analysis.
Code Analysis
From the above process we can see that the shop and Office code in the system is exactly the same. As long as the shop can be implemented, office can also clone the same. So our focus is on analyzing the shop and service code.
1, shop's Web.config and Project.cs
In the shop's Web.config, we have configured the Service site and store site, so as to facilitate the deployment of our easy to modify.
Refer to in the Project class.
Using System;
Using System.Configuration;
Namespace Amethysture.SSO.Shop
{
public class Project
{
public static string service = configurationsettings.appsettings["service"];
public static string WebSite = configurationsettings.appsettings["WebSite"];
}
}
2, Shop's Global.cs
Shop's Global.cs defines four session variables, UserID to identify user identities. Pass identifies the user's immediate status, and the security used to keep communication between the service and shop is not counterfeit. The URL holds the last requested page to ensure that the user can go to the requested page after logging in.
protected void Session_Start (Object sender, EventArgs e)
{
This. Session.add ("UserID", 0);
This. Session.add ("Pass", false);
This. Session.add ("Security", "");
This. Session.add ("Url", "");
}
3, Shop's Any.cs
The Any.cs of the shop does not contain code because the any class inherits from the page and, for code analysis, we centralize the code in the Page.cs.
Using System;
Using System.Web;
Namespace Amethysture.SSO.Shop
{
public class Any:Amethysture.SSO.Shop.Page
{
}
}
4, Shop's Page.cs
The page class has two methods, Customervalidate and initialize. The Customervalidate user checks the user's immediate status, and initialize is the information sent to the user after the page is logged in. Our focus is customervalidate.
Customervalidate is a very simple process, with conditional statements to check the status of pass, if Pass is no, the user does not log in, the page to the service validate page. What we want to analyze is the URL to be saved and the website and security parameters submitted. The role of the URL has been made clear in the previous, just to ensure that users can return to the original page after logging in. The website is to ensure that the site is accepted by the service and that the service knows which site requested the user's immediate status. Because this example is a simple example, there is no validation in the following validate whether the website is an accepted request site, but it should be validated in practical applications because the shop and service are equivalent to servers and clients, The server must check to see if the client is allowed for security reasons. Security is a very important point. Shop to the service sent is a request, do not need to ensure that the request has not been tampered with, but when the service answer shop request, you must ensure that the response data has not been tampered with. Security is designed to keep data safe.
In code, security is generated by a randomly generated number of hashes. is uncertain. and confidentiality. We can see that security is also saved in session and sent to service. We regard this security as clear text. In the back we can see that security in the service after another hash as ciphertext sent back to shop. If we put the session-saved security through the same hash method and wait until the string is the same as the cipher returned by the service, we can guarantee to some extent that the data for the service response is unmodified.
Using System;
Using System.Web;
Using System.Security.Cryptography;
Using System.Text;
Namespace Amethysture.SSO.Shop
{
public class Page:System.Web.UI.Page
{
private void Customervalidate ()
{
BOOL pass = (BOOL) this. Session["Pass"];
if (! Pass)
{
String security = "";
Random Seed = new Random ();
Security = Seed.next (1, Int. MaxValue). ToString ();
Byte[] Value;
UnicodeEncoding Code = new UnicodeEncoding ();
byte[] message = code.getbytes (security);
sha512managed arithmetic = new sha512managed ();
Value = arithmetic.computehash (message);
Security = "";
foreach (Byte o in Value)
{
Security + + (int) O + "O";
}
This. session["security"] = security;
This. session["URL"] = this. Request.rawurl;
This. Response.Redirect (Project.service + "/validate.aspx"?) Website= "+ project.website +" &security= "+ security);
}
}
protected virtual void Initialize ()
{
This. Response.Write ("This. Response.Write ("This. Response.Write ("<title> amethysture SSO Project </title>");
This. Response.Write ("<link rel=stylesheet type=\" text/css\ "href=\" "+ Project.website +"/default.css\ "");
This. Response.Write ("This. Response.Write ("<body>");
This. Response.Write ("<iframe width=\" 0\ "height=\" 0\ "src=\" "+ Project.service +"/customer.aspx\ "> </iframe>);
This. Response.Write ("<div align=\" Center\ "" ");
This. Response.Write ("Amethysture SSO Shop any Page");
This. Response.Write ("</div>");
This. Response.Write ("</body>");
This. Response.Write ("}
protected override void OnInit (EventArgs e)
{
Base. OnInit (e);
This. Customervalidate ();
This. Initialize ();
This. Response.End ();
}
}
}
5, the service Global.cs
Now our page is transferred to the Validate page of the service, and we turn to the service code. In global we also define four session variables, which are similar to shop's session use. Website is the site information that holds the immediate status of the requesting user. So that you can return to the correct request site after you log in.
protected void Session_Start (Object sender, EventArgs e)
{
This. Session.add ("UserID", 0);
This. Session.add ("Pass", false);
This. Session.add ("WebSite", "");
This. Session.add ("Security", "");
}
6, the service Validate.cs
First, save the parameters that the shop passed over to the session. If the user is not logged in, go to the customer page to sign in. If the user is already logged in. The user's immediate status is passed back to the shop site. As mentioned above, the security has been hashed back to shop to ensure that the data is not tampered with.
private void Customervalidate ()
{
BOOL pass = (BOOL) this. Session["Pass"];
if (this. request.querystring["WebSite"]!= null) && (this. request.querystring["WebSite"]!= ""))
{
This. session["WebSite"] = this. request.querystring["WebSite"];
}
if (this. request.querystring[' security ']!= null && (this. request.querystring["Security"]!= "")
{
This. session[' security ' = this. request.querystring["Security"];
}
if (pass)
{
String UserID = this. session["UserID"]. ToString ();
String WebSite = this. session["WebSite"]. ToString ();
String security = this. session["Security"]. ToString ();
Byte[] Value;
UnicodeEncoding Code = new UnicodeEncoding ();
byte[] message = code.getbytes (security);
sha512managed arithmetic = new sha512managed ();
Value = arithmetic.computehash (message);
Security = "";
foreach (Byte o in Value)
{
Security + + (int) O + "O";
}
This. Response.Redirect (WebSite + "/synchronous.aspx"?) Userid= "+ UserID +" &pass=true&security= "+ security);
}
Else
{
This. Response.Redirect ("customer.aspx");
}
}
7, the service Customer.cs and Login.cs
The main customer is a form for logging in, where no code is posted. Here is an analysis of login code, which is when the login is done directly in the service (website is null), the page does not go to the shop or office site. So it should be paused at the Service site. If the system is perfect, this should display a set of word system steering links. Below we see, when pass is true, the page turns back to the Validate page, through the above analysis, we know, the page will turn to shop's synchronous page, the user state synchronization.
if (pass)
{
if (this. session["WebSite"]. ToString ()!= "") && (this. session["Security"]. ToString ()!= ""))
{
This. Response.Redirect ("validate.aspx");
}
Else
{
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("Pass");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
}
}
Else
{
This. Response.Redirect ("customer.aspx");
}
8, Shop's Synchronous.cs
Well, we completed the login in the service and passed the user status back to the shop site. We then look at how the user status is synchronized. First, if the security in the session is an empty string, it means that the shop site did not send a request to the service, and the service sent back the request to the store, which is clearly wrong. The visit was spoofed by the client and the access was denied. The same security and insecurity are different, which means that the request and answer do not match. The answer may have been tampered with, so the answer was also rejected. When the inspection security is passed, we guarantee that the serive completes the response and returns the exact parameters, the following is the readout parameter synchronization shop site and Service site users instant status.
String Inuserid = this. request.querystring["UserID"];
String inpass = this. Request.querystring["Pass"];
String insecurity = this. request.querystring["Security"];
String security = this. session["Security"]. ToString ();
if (Security!= "")
{
Byte[] Value;
UnicodeEncoding Code = new UnicodeEncoding ();
byte[] message = code.getbytes (security);
sha512managed arithmetic = new sha512managed ();
Value = arithmetic.computehash (message);
Security = "";
foreach (Byte o in Value)
{
Security + + (int) O + "O";
}
if (Security = insecurity)
{
if (Inpass = = "True")
{
This. session["UserID"] = Int. Parse (Inuserid);
This. Session["Pass"] = true;
This. Response.Redirect (this. session["Url"]. ToString ());
}
}
Else
{
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("Data Error");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
}
}
Else
{
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("Access error");
This. Response.Write ("");
This. Response.Write ("");
This. Response.Write ("");
}
9, Shop's Page.cs
We know that the page does not refresh after a period of time, the session will expire, in the time we have been visiting the shop how to ensure that the service session will not be invalidated? Very simply, we return to see Shop's Page.cs. By using a page of <iframe> nested service on all of the shop's pages, you can ensure that the service can be refreshed with the shop's page. One thing to note is that service sessions must be guaranteed to be no less than the session timeout for all shop and office. This can be configured in web.config.
This. Response.Write (" );
Summary
A complete login is complete. Let's go ahead and assume what the system is going to do now to jump to any page in office. Any (user is not logged in)->validate (user has logged in)->synchronous (sync)->any. This time, the user does not have the process of logging in. We use a login to make the service user status log in, and no matter how many Web applications, as long as these sites are guaranteed to meet the characteristics of the shop, these sites will be able to maintain the service user status, but also through the service to obtain the user's status. That means we have SSO.