1 Overview
We will not describe the mechanism and principle of single-point logon here. This article only summarizes the experiences of the Single Sign-On problem.
There are many ways to achieve single-point Logon:
1. Use mature software frameworks (CAS, opensso, etc)
2. self-built single-point login framework (such as Sohu's single-point login)
3. Use URL to simulate logon.
However, each method has its own advantages and disadvantages. The main problem is that most of the implementation methods need to modify the single-point logon target system, or put the single-point logon code in the target system. If we do not have control over the target system, communication with the target system becomes the biggest obstacle.
If you do not need to modify the target system, or you can log on without putting the code in the target system, it is the ideal single-point logon mode. Based on this problem, it is a relatively better solution to establish a URL that imitates the login request for login. Why is it "relatively better", because there are basically page refreshes or jumps when you log on using URLs. Therefore, the design of single sign-on will become a bottleneck, especially when you want to design a non-Refresh logon or maintain Session access to the target system at any time, it will bring more restrictions to the system.
In fact, a lot of research has been conducted to address this issue recently and various methods have been used to try it out. However, there is no substantial achievement. The main problem is that the browser adopts the "Same Origin Policy" based on security considerations ).
The following describes the methods used.
2 cross-origin Solutions
2.1 Ajax
Ajax is the first method to send requests asynchronously. The original Single Sign-On method is to place code in the target system. Use a URL to access the code and send an Ajax request to log on to the code.
Because of this method, you need to place code in the target system, which cannot meet our requirements, so try to move the Ajax Login Request Code to the "Source System" (that is, a system with single sign-on function, is our portal system ). However, the request cannot be sent at all, and a prompt box is displayed in the browser: "This page is accessing data out of its control scope. This is dangerous. Continue ". Ajax itself uses the XMLHTTPRequest object to interact with data. For security reasons, the browser does not allow cross-origin operations of JavaScript code, so it will warn you.
You can use the XMLHttpRequest proxy on the server to implement cross-origin access.
We cannot directly use Ajax on the browser side to access resources across domains, but there is no such cross-domain security restriction on the server side. Therefore, you only need to ask the server side to help us complete the "cross-origin access" work, and then use Ajax on the browser side to obtain the results of the "cross-origin access" on the server side. This is called creating an XMLHttpRequest proxy on the server side to access resources under other domain names. Here we reference Yahoo! Several figures on the Javascript Developer Center further illustrate this solution:
Use XMLHttpRequest to access resources under the same domain name:
Use XMLHttpRequest to access resources across domains:
Use the XMLHttpRequest proxy on the server to access resources across domains:
The specific process of writing the XMLHttpRequest proxy on the server is not described in detail. It is nothing more than creating a custom HTTP request.
In fact, this method does not fundamentally solve the cross-origin problem of Ajax.
2.2 Javascript
A common method to solve cross-origin is to use dynamic SCRIPT tags to implement cross-origin access to the client.
Obviously, the previous scheme must be modified on the server side to implement cross-origin access. However, the source code of the server cannot be modified in many cases, so the previous solution cannot meet the requirements.
Although the browser has cross-origin access restrictions, we can use the script tag to remotely reference script files under other domain names. In addition, the src attribute of the script tag is not necessarily an existing JS file or an HTTP handler URL, as long as the HTTP handler returns a response of the text/JavaScript type.
In this way, our second solution has surfaced. The difference between this and the previous one is that the request uses the <SCRIPT> tag for the request. This requirement is also required for both domains to be developed by you. The principle is JS file injection. a js tag is generated within a in the domain. Its SRC points to a page B in another domain of the request and B returns data, you can directly return the JS Code. Because the src attribute of the script can be cross-origin. The Code is also relatively simple.
2.3 IFRAME
IFRAME usage:
1. Mutual access between the domain and subdomain: www.aa.com and book.aa.com
2. Mutual access between the domain and other domains: IFRAME for www.aa.com and www.bb.com
In the first case, if you want to achieve data interaction, you must develop www.aa.com and book.aa.com. You can use IFRAME to add book.aa.com to a page at www.aa.com and add document. Domain = "aa.com" to both www.aa.com and IFRAME to unify the domain and implement cross-origin access. Just like the built-in IFRAME in the same domain, you can directly call the Js in it. (I did not try this method, but it is theoretically feasible, and the following cross-subdomain cookie method seems better)
In the second case, if the two domains are different and you want to call each other, you also need to develop the two domains. IFRAME can be used to call data. The solution is to use the hash attribute of the window. Location object. The hash attribute is # dshakjdhsjka in http: // domian/web/a.htm # dshakjdhsjka. Using js to change the hash value does not refresh the web page. In this way, you can use js to access the hash value for communication. However, most browsers except ie only need to change the hash to record the history, and you need to handle it before and after it is very troublesome. But it can still be used for simple processing. I will download the specific code below. The general process is that page A and page B are in different domains, B is added to a through IFRAME, and a modifies the hash value of IFRAME through Js, B makes a listener (because JS can only modify the hash, and whether the data is changed can only be determined by B). It is detected that the hash value of B is modified and the modified value is obtained, after processing, return the value required by a, and then modify the hash value of A (Note that if A is the query page, such as http: // domian/web/. aspx? Id = 3, directly parent in B. window. location cannot obtain data, and an error with no permissions is reported. A needs to upload the data, which is also troublesome.) Similarly, A also needs to listen, if the hash changes, the returned data is obtained and processed accordingly.
2.4 httpclient
The following method is to use Apache's httpclient to log on.
Generally, we use the URL in system A to perform single-point logon. First, create a URL that simulates the login form submission in system A for Logon (we call this URL url1 ). If the logon is successful, you can access the website using the normal URL of system A to see the logon status (we call this URL url2 ).
The principle is the principle of the HTTP protocol. After we use url1 for access, the server will create a session for the user and set the "Set-cookie" header in the response, this information contains the corresponding sessionid. The browser generates a cookie on the client based on the information. When we access url2 again, the browser will determine whether a cookie has been created in the session. If a cookie has been created, the browser will add the cookie header information in the request, which contains the corresponding sessionid. When the server processes messages, it determines whether the sessionid is the same. If the sessionid is the same, it is considered to be the same session and the same person.
This is the solution to the stateless HTTP protocol. However, the premise is that you are using the same browser. Like IE7, although multiple tabs may be opened, it is still the same browser.
You can use httpclient to simulate sending a request and log on to the target system. But the principle of httpclient is that every time a link is established, it is equivalent to opening a new browser. Then, access to url1 and url2 respectively according to the above process will be simulated to open two browsers. In other words, the cookie message header will not be carried when you access url2, the server will think that it is not the same session and will not simulate a Successful Logon status.
According to the above description, the crux of the problem is: when sending a request to access url2, you can bring the cookie information returned by url1.
To enable the cookie header when accessing url2, you can use the following methods:
1. Create a cookie on the client after accessing url1
2. When accessing url2, add cookie header information to the message header.
3. When accessing url2, rewrite the URL and add the information in the cookie header to the URL.
Generally, the above three operations do not need to be done by ourselves. They can be automatically completed by the server and system. However, in system B, you can log on to system A by accessing url1 and url2 of system A, which causes problems.
2.5 cross-origin cookie
1. Access the url1 of system a from system B. For the sake of same-source policy security, the browser will prohibit system a from generating cookies.
2. Unfortunately, J2EE does not provide a method to add the cookie header to the request header.
3. This method is only feasible. However, if system B references a system with too many URLs similar to url2, URL rewriting is a work of adding one part.
In summary, because of the same-origin policy, the cookie cannot be shared, and the session connection cannot be maintained. However, the same-origin policy supports cross-subdomain cookies.
2.6 cross-subdomain cookie
The so-called cross-subdomain login, A, B site and P site are located under the same domain, such as site A for the http://blog.yizhu2000.com, site B for the http://forum.yizhu2000.com, they and login site P relationship can be seen, all belong to the same parent domain, yizhu2000.com. Different subdomains are different. One is blog, the other is forum, and the other is passport. Let's first look at the most common non-Cross-Site normal logon situations, generally, your user name and some user information are encrypted by a key and written locally, which is an encrypted cookie, we call this cookie a ticket ).
To determine whether the user is logged on to the page, read the ticket and decrypt the user information from it. If the ticket does not exist or cannot be decrypted, it means that the user has not logged on or the login information is incorrect, at this time, we will jump to the login page to log on. Here, encryption has two functions: one is to prevent user information from being viewed by malicious users, and the other is to ensure that ticket will not be forged. The latter is actually more important, after encryption, each application needs to use the same key as the encryption for decryption. If you do not know the key, you cannot forge a ticket. (Note: the encryption and decryption keys may be different, it depends on the encryption algorithm used. If it is symmetric encryption, it is the same key. If it is not symmetric, it is different. Generally, it is encrypted with the private key and decrypted with the public key. However, the key is only known internally, so that the counterfeiter cannot forge or decrypt ticket)
The cross-subdomain single-point logon process is no different from the preceding normal logon process. The only difference is that when the cookie is written, because the login site P and application a are in different subdomains, the cookie domain written by the P site is passport.yizhu2000.net, and site A is forum.yizhu2000.net. A cannot read the ticket of the P site when judging the user's logon.
The solution is very simple. When the P site writes ticket after login is complete, you only need to set the cookie domain to their common parent domain, and yizhu2000.net will be able to: cookie. domain = "yizhu2000.net", Site A can naturally read this ticket.
2.7 p3p
If you have checked information on the Internet, you can set cookies for different domains by adding the p3p header to the response header. The setting method is as follows:
Step 1:
First, set it in the hosts file (192.168.73.1 is the IP address of your local machine, which cannot be written as 127.0.0.1 .) For example, this is not required on a real server.
192.168.73.1 www.a.com
192.168.73.1 www. B .com
Step 2: Compile the file B _setcookie.jsp
[Java]View plaincopy
- <% @ Page contenttype = "text/html; charset = UTF-8" %>
- <%
- Response. addheader ("cache-control", "No-Cache ");
- Response. addheader ("expires", "Thu, 01 Jan 1970 00:00:01 GMT ");
- String ssocookie = "www.sso12345678910.com ";
- %>
- <MCE: script src = "http://www.a.com/mp/test/a_setcookie.jsp? Id = <% = ssocookie %> <! --
- ">
- // --> </MCE: SCRIPT>
Step 3: Compile the file a_setcookie.jsp
[Java]View plaincopy
- <%
- Response. setheader ("p3p", "cp =/" Cura ADMA Deva psao psdo our bus uni pur int DEM sta pre com nav OTC Noi dsp cor /"");
- String domainid = request. getparameter ("ID ");
- Cookie _ cookie = new cookie ("test", domainid );
- _ Cookie. setmaxage (30*60*100 );
- _ Cookie. setpath ("/");
- Response. addcookie (_ cookie );
- %>
Step 4: Write the file a_getcookie.jsp
[Java]View plaincopy
- <% @ Page contenttype = "text/html; charset = UTF-8" %>
- <%
- Cookie Cookies [] = request. getcookies (); cookie scookie = NULL;
- String sname = NULL;
- String name = NULL;
- If (cookies = NULL) // if no cookie exists
- Out. Print ("none any cookie ");
- Else {
- Out. Print (cookies. Length + "<br> ");
- For (INT I = 0; I <cookies. length; I ++ ){
- Scookie = Cookies [I];
- Sname = scookie. getname ();
- Name = scookie. getvalue ();
- Out. println ("comment ==>>>" + scookie. getcomment () + "/N ");
- Out. println ("getdomain ==>>>" + scookie. getdomain () + "/N ");
- Out. println ("getsecure ==>>" + scookie. getsecure () + "/N ");
- Out. println ("getversion ==>>" + scookie. getversion () + "/N ");
- Out. println ("cookiename ==>>" + sname + "->" + "cookievalue ==>>>" + name + "<br> ");
- }
- }
- %>
Step 5: Test
Requests in turn
Http://www. B .com/mp/test/ B _setcookie.jsp
Http://www.a.com/mp/test/a_getcookie.jsp
You can see the cookie value set through cross-origin!
Although this method can implement cross-origin cookie setting, it still needs to inject code in the target system.
3. digress
In fact, crystal easy table flash cannot access WebService across domains to obtain the number of corners, which is also caused by the Security Sandbox problem similar to the same-source policy.
There are also corresponding solutions to the security sandbox problem.
If you want to obtain data across domains in flash, you must configure crossdomain. xml on the opposite server. Specifically, for example, if your flash is under Domain A and you want to access the Web Service exposed by Domain B, you must have a crossdomain under the server root directory of Domain B. you have the permission to configure the XML file. This is the security restriction of Flash Player.
For versions earlier than Flash Player 9, The crossdomain. xml file is roughly as follows:
[XHTML]View plaincopy
- <? XML version = "1.0" encoding = "UTF-8"?>
- <! Doctype cross-domain-Policy System "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
- <Cross-domain-Policy>
- <Allow-access-from domain = "*" secure = "true"/>
- </Cross-Domain-Policy>
The preceding configuration allows all domains to access the data exposed by the current server (such as Web Service ). You can specify special rules in the domain attribute. The secure attribute is used to set whether your exposed data adopts the HTTPS protocol.
However, for Flash Player 9, The crossdomain. xml file content has changed significantly because the security mechanism of Flash Player 9 has changed. Therefore, when I use Flex 3 to call the Cross Domain web service, the above crossdomain. xml file is also used, and the result returns an error saying security error. So I studied it a little and got the following solution, which is actually to change the content of crossdomain. xml:
[XHTML]View plaincopy
- <? XML version = "1.0" encoding = "UTF-8"?>
- <! Doctype cross-domain-Policy System "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
- <Cross-domain-Policy>
- <Site-control permitted-Cross-Domain-policies = "all"/>
- <Allow-access-from domain = "*"/>
- <Allow-http-request-headers-from domain = "*" headers = "*"/>
- </Cross-Domain-Policy>
The above is the crossdomain. XML content required by Flash Player 9. We can see two more tags. Site-control is optional, but allow-http-request-headers-from is required for cross-domain Web Services. If the header is not allowed, an error will be reported as before. For more information about the meanings and other optional configuration items, see http://www.adobe.com/devnet/flashplayer/articles/flash_player_9_security.htm.
Of course, in the generated flash, code is required to call the corresponding crossdomain. xml. However, this code is not included in the Flash exported by the crystal table.
Summary of Single Sign-On Problems