SSO單點登陸

  單點登陸(Single Sign On),簡稱爲SSO,SSO不只在企業級開發很經常使用,在互聯網中更是大行其道。隨便舉幾個例子,好比咱們登陸新浪微博後,再訪問新浪首頁後,咱們發現, 已經自動登陸了;再好比咱們登陸CSDN後,能夠寫博客、逛論壇、下載資源等等。前者是徹底跨域的單點登陸,下文會講,後者是共同父域下 (www.csdn.NET、blog.csdn.net、bbs.csdn.Net、passport.csdn.net)的單點登陸,也就是本文的主要內容。html

 

 

 

-------------------------1.同域名下的應用的單點登陸-----------------------------------java

   思路:統一登陸接口要根據其訪問的地址設置登錄成功後跳轉的頁面。好比你在動物園在景點1被攔截了要求你買票你確定是買一張通票而後繼續訪問景點1。具體的作法就是在登陸表單中隱藏一個跳轉的頁面,而後在登陸校驗成功以後跳轉到隱藏表單提交上來的跳轉頁面。web

1.準備環境apache

將動態項目映射的項目名字去掉跨域

  在tomcat的conf文件夾下的server.xml配置:tomcat

<Context docBase="E:\tomcat\apache-tomcat-7.0.72\wtpwebapps\SSO_SameDomain" path="" reloadable="true" source="org.eclipse.jst.jee.server:SSO_SameDomain"/>

 

 

  或者在eclipse中配置:服務器

  倒入struts2的jar包,配置web.xml中struts的過濾器。cookie

2.統一登錄接口網絡

登錄頁面:(login.jsp)app

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="qlq">
  <meta name="Keywords" content="">
  <meta name="Description" content="單點登陸的界面">
  <title>登陸界面</title>
 </head>
 <body>
    <center>
        <h3>請登陸</h3>
        <form action=""  method="post">
            用戶名:<input type="text" name="username"/>
            &nbsp;&nbsp;&nbsp;&nbsp;
            密碼:<input type="password" name="password"/>
            <input type="hidden" name="gotoUrl" value="${goroUrl}"/>
            <input type="submit" value="登陸"/>
        </form>
    </center>
 </body>
</html>

 

處理登錄的Action

  訪問主頁的時候設置一個goroUrl,用於標記成功以後要重定向的頁面(是demo1的主頁仍是demo2的主頁)。登錄的時候帶着gotoUrl訪問登錄Action,成功以後跳轉到goroUrl對應的頁面

package SSOAction;

import java.awt.image.VolatileImage;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

public class LoginAction extends ActionSupport {

    private String username;
    private String password;
    private String gotoUrl;
    
    


    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String execute() throws Exception {
        boolean OK = this.check();
        if (OK) {
            Cookie cookie = new Cookie("sscookie", "sso");
            // 設置cookie的做用範圍是頂層(localhost),在localhost域下的應用可見
            cookie.setPath("/");
            HttpServletResponse response = ServletActionContext.getResponse();
            // 增長cookie,未設置生命週期默認爲一次會話
            response.addCookie(cookie);
            return SUCCESS;
        }
        return null;
    }

    public boolean check() {
        if ("user".equals(username) && "123".equals(password))
            return true;
        return false;
    }

}

 

struts.xml配置登錄的Action

    <package name="sso" namespace="/sso" extends="struts-default">
        <action name="login" class="SSOAction.LoginAction">
            <result name="success" type="redirect">${goroUrl}</result>
        </action>
    </package>

 

2.登錄校驗接口

  檢查cookie中是否攜帶登錄信息

package utils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CheckCookie {

    public static boolean checkCookie(HttpServletRequest request) {
        Cookie cookies[] = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                // 驗證是否存在cookie
                if ("ssocookie".equals(cookie.getName()) && "sso".equals(cookie.getValue()))
                    return true;
            }
        }

        return false;
    }
}

 

3.  編寫demo1主頁和demo2主頁(struts2中Action的屬性名字有get,Set方法屬性會被放到值棧中)

 

demo1的主頁:

 Demo1Index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>歡迎訪問Demo1的主頁</title>
</head>
<body>歡迎訪問Demo1的主頁,這是Demo1的主頁。~~~~~~~~~~~~~~~~~~
<s:debug></s:debug>
</body>
</html>

 

  處理登錄的Axtion,登錄以前先驗證cookie,成功跳到demo1主頁,失敗將主頁寫到gotoUrl

package Demo1;

import javax.print.attribute.standard.RequestingUserName;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

import utils.CheckCookie;

/**
 * Demo1主頁,訪問主頁要先驗證cookie
 * 
 * @author: qlq
 * @date : 2017年8月29日下午12:02:31
 */
public class Demo1Action extends ActionSupport {

    private String gotoUrl;

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        if (CheckCookie.checkCookie(request))
            return SUCCESS;
        // 登錄失敗後將gotoUrl寫到JSP頁面
        gotoUrl = "/demo1/main.action";
        return LOGIN;
    }

}

 

demo2的主頁:

  Demo2Index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>歡迎訪問Demo2的主頁</title>
</head>
<body>歡迎訪問Demo2的主頁,這是Demo2的主頁。
</body>
</html>

 

  處理登錄的Axtion,登錄以前先驗證cookie,成功跳到demo2主頁,失敗將主頁寫到gotoUrl

package Demo2;

import javax.print.attribute.standard.RequestingUserName;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

import utils.CheckCookie;

/**
 * Demo2主頁,訪問主頁要先驗證cookie
 * 
 * @author: qlq
 * @date : 2017年8月29日下午12:02:31
 */
public class Demo2Action extends ActionSupport {

    private String gotoUrl;

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        if (CheckCookie.checkCookie(request))
            return SUCCESS;
        // 登錄失敗後將gotoUrl寫到JSP頁面
        gotoUrl = "/demo2/main.action";
        return LOGIN;
    }

}

 

struts.xml中配置主頁

    <package name="demo1" namespace="/demo1" extends="struts-default">
        <action name="main" class="Demo1.Demo1Action">
            <result name="success">/Demo1Index.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>

    <package name="demo2" namespace="/demo2" extends="struts-default">
        <action name="main" class="Demo2.Demo2Action">
            <result name="success">/Demo2Index.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>

 

4.啓動tomcat測試

1.  訪問: http://localhost:8080/demo1/main.action

 

查看項目源碼:

2.  訪問: http://localhost:8080/demo2/main.action

查看頁面源碼:

3.在demo2中登錄

 

 

4.刷新demo1.action(已經登錄成功)

5.查看cookie

 

6.調整3與4d順序,先登陸1,再刷新2,結果同樣

 

-------------------------------------------------共同父域下的SSO------------------------------

0.  首先了解下域名的概念與結構:

域名就是對應於IP地址的用於在互聯網上標識機器的有意義的字符串。

聯網上的域名就至關於咱們現實生活中的門牌號碼同樣,能夠在紛繁蕪雜的網絡世界 裏準確無誤地把咱們指引到咱們要訪問的站點。在互聯網發展之初並無域名,有的只是IP地址。IP地址就是一組相似這樣的數字, 如:162.105.203.245。因爲當時互聯網主要應用在科研領域,使用者很是少,因此記憶這樣的數字並非很是困難。可是隨着時間的推移,連入互 聯網的電腦愈來愈多,須要記憶的IP地址也愈來愈多,記憶這些數字串變得愈來愈困難,因而域名應運而生。域名就是對應於IP地址的用於在互聯網上標識機器 的有意義的字符串。例如CNNIC的域名WWW.CNNIC.NET.CN,比起IP地址而言就更形象也更容易記憶。

  爲了便於你們進一步瞭解域名的實質,有必要在這裏談談域名的體系結構。從WWW.CNNIC.NET.CN 這個域名來看,它是由幾個不一樣的部分組成的,這幾個部分彼此之間具備層次關係。其中最後的.CN是域名的第一層,.NET是第二層,.CNNIC是真正的 域名,處在第三層,固然還能夠有第四層,如:INNER.CNNIC.NET.CN,至此咱們能夠看出域名從後到前的層次結構相似於一個倒立的樹型結構。 其中第一層的.CN叫作地理頂級域名。

  目前互聯網上的域名體系中共有三類頂級域名:一是地理頂級域名,共有243個國家和地區的代碼。例如.CN 表明中國,.JP表明日本,.UK表明英國等等,另外一類是類別頂級域名,共有7個:.COM(公司),.NET(網絡機構),.ORG(組織機 構),.EDU(美國教育),.GOV(美國政府部門),.ARPA(美國軍方),.INT(國際組織)。因爲互聯網最初是在美國發展起來的,因此最初的 域名體系也主要供美國使用,因此.GOV,.EDU,.ARPA雖然都是頂級域名,但倒是美國使用的。只有.COM,.NET,.ORG成了供全球使用的 頂級域名。相對於地理頂級域名來講,這些頂級域名都是根據不一樣的類別來區分的,因此稱之爲類別頂級域名。隨着互聯網的不斷髮展,新的頂級域名也根據實際需 要不斷被擴充到現有的域名體系中來。新增長的頂級域名是.BIZ(商業),.COOP(合做公司),.INFO(信息行業),.AERO(航空 業),.PRO(專業人士),.MUSEUM(博物館行業),.NAME(我的)。

  在這些頂級域名下,還能夠再根據須要定義次一級的域名,如在我國的頂級域名.CN下又設立了.COM,.NET,.ORG,.GOV,.EDU以及我國各個行政區劃的字母表明如.BJ表明北京,.SH表明上海等等。

 

 

 

 

 

1.準備工做:

修改C:\Windows\System32\drivers\etc\hosts文件,增長域名的映射

2.準備統一登陸接口

login.JSP

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="qlq">
  <meta name="Keywords" content="">
  <meta name="Description" content="單點登陸的界面">
  <title>登陸界面</title>
 </head>
 <body>
    <center>
        <h3>請登陸</h3>
        <form action="http://check.x.com:8080/sso/login.action"  method="post">
            用戶名:<input type="text" name="username" value="user"/>
            &nbsp;&nbsp;&nbsp;&nbsp;
            密碼:<input type="password" name="password" value="123"/>
            <input type="hidden" name="gotoUrl" value="${gotoUrl}"/>
            <input type="submit" value="登陸"/>
        </form>
    </center>
 </body>
</html>

 

處理登陸的Action(設置cookie爲父域下的全部應用可見)

package check.x.com;

import java.awt.image.VolatileImage;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

public class LoginAction extends ActionSupport {

    private String username;
    private String password;
    private String gotoUrl;

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String execute() throws Exception {
        boolean OK = this.check();
        if (OK) {
            Cookie cookie = new Cookie("ssocookie", "sso");
            // 設置cookie的做用範圍是父域(.x.com)
            cookie.setDomain(".x.com");
            // 斜槓表明設置到父域的頂層,也就是父域下的全部應用均可訪問
            cookie.setPath("/");
            HttpServletResponse response = ServletActionContext.getResponse();
            // 增長cookie,未設置生命週期默認爲一次會話
            response.addCookie(cookie);
            return SUCCESS;
        }
        return null;
    }

    public boolean check() {
        if ("user".equals(username) && "123".equals(password))
            return true;
        return false;
    }

}

 

struts.xml配置Action

    <package name="sso" namespace="/sso" extends="struts-default">
        <action name="login" class="check.x.com.LoginAction">
            <result name="success" type="redirect">${gotoUrl}</result>
        </action>
    </package>

 

3.準備統一登陸校驗接口

  在check.x.com中校驗,首先根據demo1.x.com傳來的cookieName和cookieValue進行校驗,若是校驗經過,經過response返回1,不經過返回0。

校驗工具類

package check.x.com.utils;


public class CheckCookie {

    public static boolean checkCookie(String cookieName, String cookieValue) {
        // 驗證是否存在cookie
        if ("ssocookie".equals(cookieName) && "sso".equals(cookieValue))
            return true;
        return false;
    }
}

 

校驗類:checkCookie()方法

package check.x.com;

import java.awt.image.VolatileImage;
import java.io.IOException;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import check.x.com.utils.CheckCookie;

public class LoginAction extends ActionSupport {

    private String username;
    private String password;
    private String gotoUrl;
    private String cookieName;
    private String cookieValue;

    public String getCookieName() {
        return cookieName;
    }

    public void setCookieName(String cookieName) {
        this.cookieName = cookieName;
    }

    public String getCookieValue() {
        return cookieValue;
    }

    public void setCookieValue(String cookieValue) {
        this.cookieValue = cookieValue;
    }

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String execute() throws Exception {
        boolean OK = this.check();
        if (OK) {
            Cookie cookie = new Cookie("ssocookie", "sso");
            // 設置cookie的做用範圍是父域(.x.com)
            cookie.setDomain(".x.com");
            // 斜槓表明設置到父域的頂層,也就是父域下的全部應用均可訪問
            cookie.setPath("/");
            HttpServletResponse response = ServletActionContext.getResponse();
            // 增長cookie,未設置生命週期默認爲一次會話
            response.addCookie(cookie);
            return SUCCESS;
        }
        return null;
    }
    
    
    public void checkCookie() throws IOException{
        String result="0";
        if(CheckCookie.checkCookie(cookieName, cookieValue)){
            result="1";
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
    }

    public boolean check() {
        if ("user".equals(username) && "123".equals(password))
            return true;
        return false;
    }

}

 

struts.xml中配置驗證cookie的action(沒有跳轉頁面,只是返回數據)

 

4.編寫demo1的主頁及處理的Action

Demo1Index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>歡迎訪問Demo1的主頁</title>
</head>
<body>歡迎訪問Demo1的主頁,這是Demo1的主頁。~~~~~~~~~~~~~~~~~~
</body>
</html>

 

Demo1Action.java

package demo1.x.com;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.print.attribute.standard.RequestingUserName;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

/**
 * Demo1主頁,訪問主頁要先驗證cookie
 * 
 * @author: qlq
 * @date : 2017年8月29日下午12:02:31
 */
public class Demo1Action extends ActionSupport {

    private String gotoUrl;

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        Cookie cookies[] = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("ssocookie".equals(cookie.getName())) {
                    String result = this.doGet("http://check.x.com:8080/sso/checkCookie.action", cookie.getName(),
                            cookie.getValue());
                    if ("1".equals(result)) {
                        return SUCCESS;
                    }
                }
            }
        }
        // 登錄失敗後將gotoUrl寫到JSP頁面
        gotoUrl = "http://demo1.x.com:8080/demo1/main.action";
        return LOGIN;
    }

    public String doGet(String url, String cookieName, String cookieValue) {
        // 用於接收返回的數據
        StringBuffer sb = new StringBuffer();
        // 建立一個鏈接的請求
        HttpURLConnection httpURLConnection = null;
        try {
            // 包裝請求的地址
            URL urls = new URL(url + "?cookieName=" + cookieName + "&cookieValue=" + cookieValue);
            // 打開鏈接
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            httpURLConnection.setRequestMethod("GET");
            // 經過BufferReader讀取數據
            InputStream iStream = httpURLConnection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(iStream);
            BufferedReader bReader = new BufferedReader(inputStreamReader);
            String temp = null;
            while ((temp = bReader.readLine()) != null) {
                sb.append(temp);
            }
            // 關閉流(先開後關,後開先關)
            bReader.close();
            inputStreamReader.close();
            iStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (httpURLConnection != null) {
                // 關閉鏈接
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
    }

}

 

 

 

 

 

Demo2Index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>歡迎訪問Demo2的主頁</title>
</head>
<body>歡迎訪問Demo2的主頁,這是Demo2的主頁。
</body>
</html>

 

Demo2Action.java

package demo2.x.com;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.print.attribute.standard.RequestingUserName;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

/**
 * Demo2主頁,訪問主頁要先驗證cookie
 * 
 * @author: qlq
 * @date : 2017年8月29日下午12:02:31
 */
public class Demo2Action extends ActionSupport {

    private String gotoUrl;

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        Cookie cookies[] = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("ssocookie".equals(cookie.getName())) {
                    String result = this.doGet("http://check.x.com:8080/sso/checkCookie.action", cookie.getName(),
                            cookie.getValue());
                    if ("1".equals(result)) {
                        return SUCCESS;
                    }
                }
            }
        }
        // 登錄失敗後將gotoUrl寫到JSP頁面
        gotoUrl = "http://demo2.x.com:8080/demo2/main.action";
        return LOGIN;
    }

    public String doGet(String url, String cookieName, String cookieValue) {
        // 用於接收返回的數據
        StringBuffer sb = new StringBuffer();
        // 建立一個鏈接的請求
        HttpURLConnection httpURLConnection = null;
        try {
            // 包裝請求的地址
            URL urls = new URL(url + "?cookieName=" + cookieName + "&cookieValue=" + cookieValue);
            // 打開鏈接
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            httpURLConnection.setRequestMethod("GET");
            // 經過BufferReader讀取數據
            InputStream iStream = httpURLConnection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(iStream);
            BufferedReader bReader = new BufferedReader(inputStreamReader);
            String temp = null;
            while ((temp = bReader.readLine()) != null) {
                sb.append(temp);
            }
            // 關閉流(先開後關,後開先關)
            bReader.close();
            inputStreamReader.close();
            iStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (httpURLConnection != null) {
                // 關閉鏈接
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
    }

}

 

 

struts.xml中配置

    <package name="demo1" namespace="/demo1" extends="struts-default">
        <action name="main" class="demo1.x.com.Demo1Action">
            <result name="success">/Demo1Index.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>

    <package name="demo2" namespace="/demo2" extends="struts-default">
        <action name="main" class="demo2.x.com.Demo2Action">
            <result name="success">/Demo2Index.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>

 

5.啓動tomcat進行測試:

1.訪問:http://demo1.x.com:8080/demo1/main.action

 

查看頁面源碼

 

2.訪問:http://demo2.x.com:8080/demo2/main.action

查看頁面源碼:

3.在demo1中登陸:

 

 查看網絡

 

4.刷新demo2

 

 -------------------------------徹底跨域的SSO-----------------------------------

 

0.思路:

  表單提交的時候 提交到本域,本域帶着用戶名與密碼去驗證服務器進行驗證,驗證經過的時候增長cookie,增長cookie的時候在頁面中經過隱藏iframe經過增長cookie到本域與另外一個域;驗證cookie的時候也是本域帶着cookie名字與值去驗證服務器進行驗證,驗證服務器返回驗證結果。

 

1.準備環境

修改C:\Windows\System32\drivers\etc\hosts文件,增長域名的映射

 

修改tomcat\conf\server.xml

 

 

2.編寫同一登陸接口

login.jsp(處理登陸提交地址是在本域。而後本域帶着用戶名和密碼向驗證服務器提交請求)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="qlq">
<meta name="Keywords" content="">
<meta name="Description" content="單點登陸的界面">
<title>登陸界面</title>
</head>
<body>
    <center>
        <h3>請登陸</h3>
        <!-- 向當前本域提交登陸申請,處理登陸與cookie驗證在其它域處理 -->
        <form action="/${path }/sso/login.action" method="post">
            用戶名:<input type="text" name="username" value="user" />
            &nbsp;&nbsp;&nbsp;&nbsp; 密碼:<input type="password" name="password"
                value="123" /> <input type="hidden" name="gotoUrl"
                value="${gotoUrl}" /> <input type="submit" value="登陸" />
        </form>
    </center>
</body>
</html>

 

 

Demo1.action中處理登陸請求:doLogin()方法----帶着用戶名與密碼向驗證服務器提交請求

package www.a.com;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.print.attribute.standard.RequestingUserName;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

/**
 * Demo1主頁,訪問主頁要先驗證cookie
 * 
 * @author: qlq
 * @date : 2017年8月29日下午12:02:31
 */
public class Demo1Action extends ActionSupport {

    private String gotoUrl;
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    @Override
    public String execute() throws Exception {
        /*
         * HttpServletRequest request = ServletActionContext.getRequest();
         * Cookie cookies[] = request.getCookies(); if (cookies != null) { for
         * (Cookie cookie : cookies) { if ("ssocookie".equals(cookie.getName()))
         * { String result =
         * this.doGet("http://check.x.com:8080/sso/checkCookie.action",
         * cookie.getName(), cookie.getValue()); if ("1".equals(result)) {
         * return SUCCESS; } } } }
         */
        // 登錄失敗後將gotoUrl寫到JSP頁面
        gotoUrl = "http://demo1.x.com:8080/demo1/main.action";
        return LOGIN;
    }

    /**
     * 登陸方法
     * 
     * @return
     */
    public String doLogin() {
        Map<String, Object> map = new HashMap<>();
        map.put("username", username);
        map.put("password", password);
        String result = this.doGet("http://www.x.com/sso/doLogin.action", map);
        if ("1".equals(result)) {
            return SUCCESS;
        }
        return LOGIN;
    }

    /*
     * 驗證方法
     */
    public String doGet(String url, Map<String, Object> map) {
        // 用於接收返回的數據
        StringBuffer sb = new StringBuffer();
        // 建立一個鏈接的請求
        HttpURLConnection httpURLConnection = null;
        try {
            StringBuffer t_s = new StringBuffer(url).append("?");
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                t_s.append(entry.getKey() + "=" + entry.getValue() + "&");
            }
            url = t_s.substring(0, t_s.length() - 1);
            // 包裝請求的地址
            URL urls = new URL(url);
            // 打開鏈接
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            httpURLConnection.setRequestMethod("GET");
            // 經過BufferReader讀取數據
            InputStream iStream = httpURLConnection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(iStream);
            BufferedReader bReader = new BufferedReader(inputStreamReader);
            String temp = null;
            while ((temp = bReader.readLine()) != null) {
                sb.append(temp);
            }
            // 關閉流(先開後關,後開先關)
            bReader.close();
            inputStreamReader.close();
            iStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (httpURLConnection != null) {
                // 關閉鏈接
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
    }

}

 

Demo2.action中處理登陸請求:doLogin()方法----帶着用戶名與密碼向驗證服務器提交請求

package www.b.com;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.print.attribute.standard.RequestingUserName;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

/**
 * Demo1主頁,訪問主頁要先驗證cookie
 * 
 * @author: qlq
 * @date : 2017年8月29日下午12:02:31
 */
public class Demo2Action extends ActionSupport {

    private String gotoUrl;
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    @Override
    public String execute() throws Exception {
        /*
         * HttpServletRequest request = ServletActionContext.getRequest();
         * Cookie cookies[] = request.getCookies(); if (cookies != null) { for
         * (Cookie cookie : cookies) { if ("ssocookie".equals(cookie.getName()))
         * { String result =
         * this.doGet("http://check.x.com:8080/sso/checkCookie.action",
         * cookie.getName(), cookie.getValue()); if ("1".equals(result)) {
         * return SUCCESS; } } } }
         */
        // 登錄失敗後將gotoUrl寫到JSP頁面
        gotoUrl = "http://demo1.x.com:8080/demo1/main.action";
        return LOGIN;
    }

    /**
     * 登陸方法
     * 
     * @return
     */
    public String doLogin() {
        Map<String, Object> map = new HashMap<>();
        map.put("username", username);
        map.put("password", password);
        String result = this.doGet("http://www.x.com/sso/doLogin.action", map);
        if ("1".equals(result)) {
            return SUCCESS;
        }
        return LOGIN;
    }

    /*
     * 驗證方法
     */
    public String doGet(String url, Map<String, Object> map) {
        // 用於接收返回的數據
        StringBuffer sb = new StringBuffer();
        // 建立一個鏈接的請求
        HttpURLConnection httpURLConnection = null;
        try {
            StringBuffer t_s = new StringBuffer(url).append("?");
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                t_s.append(entry.getKey() + "=" + entry.getValue() + "&");
            }
            url = t_s.substring(0, t_s.length() - 1);
            // 包裝請求的地址
            URL urls = new URL(url);
            // 打開鏈接
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            httpURLConnection.setRequestMethod("GET");
            // 經過BufferReader讀取數據
            InputStream iStream = httpURLConnection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(iStream);
            BufferedReader bReader = new BufferedReader(inputStreamReader);
            String temp = null;
            while ((temp = bReader.readLine()) != null) {
                sb.append(temp);
            }
            // 關閉流(先開後關,後開先關)
            bReader.close();
            inputStreamReader.close();
            iStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (httpURLConnection != null) {
                // 關閉鏈接
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
    }

}

 

LoginAction.java 驗證服務器處理登陸請求(接收上面帶來的用戶名與密碼進行驗證,不用設置cookie,只用設置返回驗證結果)

package www.x.com;

import java.awt.image.VolatileImage;
import java.io.IOException;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import www.x.com.utils.CheckCookie;

public class LoginAction extends ActionSupport {

    private String username;
    private String password;
    private String gotoUrl;
    private String cookieName;
    private String cookieValue;

    public String getCookieName() {
        return cookieName;
    }

    public void setCookieName(String cookieName) {
        this.cookieName = cookieName;
    }

    public String getCookieValue() {
        return cookieValue;
    }

    public void setCookieValue(String cookieValue) {
        this.cookieValue = cookieValue;
    }

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * 驗證登陸信息
     * 
     * @throws IOException
     */
    public void doLogin() throws IOException {
        boolean OK = this.check();
        String result = "0";
        if (OK) {
            result = "1";
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
    }

    public void checkCookie() throws IOException {
        String result = "0";
        if (CheckCookie.checkCookie(cookieName, cookieValue)) {
            result = "1";
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
    }

    public boolean check() {
        if ("user".equals(username) && "123".equals(password))
            return true;
        return false;
    }

}

 

struts.xml進行配置

    <package name="sso" namespace="/sso" extends="struts-default">
        <!-- 只是驗證,沒有返回值 -->
        <action name="doLogin" class="www.x.com.LoginAction" method="doLogin">
        </action>
    </package>

    <package name="demo1" namespace="/demo1" extends="struts-default">
        <action name="main" class="www.a.com.Demo1Action" method="doLogin">
            <result name="success">/Demo1Index.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>

    <package name="demo2" namespace="/demo2" extends="struts-default">
        <action name="main" class="www.b.com.Demo2Action" method="doLogin">
            <result name="success">/Demo2Index.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>

3.登陸校驗接口----------------LoginAction.java檢驗cookie是否有效

    public void checkCookie() throws IOException {
        String result = "0";
        if ("ssocookie".equals(cookieName) && "sso".equals(cookieValue)) {
            result = "1";
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
    }

 

struts.xml進行配置

4.編寫Demo1和Demo2主頁

  兩個成功頁面都是成功後加載主頁時訪問域名a與域名b下的添加cookie的方法(經過隱藏的iframe能夠實現),cookie添加在本域下面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>歡迎訪問Demo2的主頁</title>
</head>
<body>
    歡迎訪問Demo2的主頁,這是Demo2的主頁。
    <!--成功以後隱藏一個設置cookie的鏈接  -->
    <c:forEach var="url" items="${hiddenurls }">
        <iframe src="${url }" width="0px" height="0px" style="display: none"></iframe>
    </c:forEach>
</body>
</html>

 

主頁處理增長cookie

package www.a.com;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.print.attribute.standard.RequestingUserName;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

/**
 * Demo1主頁,訪問主頁要先驗證cookie
 * 
 * @author: qlq
 * @date : 2017年8月29日下午12:02:31
 */
public class Demo1Action extends ActionSupport {

    private String gotoUrl;
    private String username;
    private String password;
    private String path;
    private List<String> hiddenurls;

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getGotoUrl() {
        return gotoUrl;
    }

    public void setGotoUrl(String gotoUrl) {
        this.gotoUrl = gotoUrl;
    }

    public List<String> getHiddenurls() {
        return hiddenurls;
    }

    public void setHiddenurls(List<String> hiddenurls) {
        this.hiddenurls = hiddenurls;
    }

    @Override
    public String execute() throws Exception {

        HttpServletRequest request = ServletActionContext.getRequest();
        Cookie cookies[] = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("ssocookie".equals(cookie.getName())) {
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("cookieName", cookie.getName());
                    map.put("cookieValue", cookie.getValue());
                    String result = this.doGet("http://www.x.com/sso/checkCookie.action", map);
                    if ("1".equals(result)) {
                        return SUCCESS;
                    }
                }
            }
        }
        // 登錄失敗後將gotoUrl寫到JSP頁面
        path = "demo1";
        gotoUrl = "http://www.a.com/demo1/main.action";
        return LOGIN;
    }

    public void addCookie() {
        Cookie cookie = new Cookie("ssocookie", "sso");
        cookie.setPath("/");
        HttpServletResponse response = ServletActionContext.getResponse();
        response.addCookie(cookie);
    }

    /**
     * 登陸方法
     * 
     * @return
     */
    public String doLogin() {
        Map<String, Object> map = new HashMap<>();
        map.put("username", username);
        map.put("password", password);
        String result = this.doGet("http://www.x.com/sso/doLogin.action", map);
        if ("1".equals(result)) {
            hiddenurls = new ArrayList<>();
            hiddenurls.add("http://www.a.com/demo1/addCookie.action");
            hiddenurls.add("http://www.b.com/demo2/addCookie.action");
            return SUCCESS;
        }
        return LOGIN;
    }

    /*
     * 驗證方法
     */
    public String doGet(String url, Map<String, Object> map) {
        // 用於接收返回的數據
        StringBuffer sb = new StringBuffer();
        // 建立一個鏈接的請求
        HttpURLConnection httpURLConnection = null;
        try {
            StringBuffer t_s = new StringBuffer(url).append("?");
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                t_s.append(entry.getKey() + "=" + entry.getValue() + "&");
            }
            url = t_s.substring(0, t_s.length() - 1);
            // 包裝請求的地址
            URL urls = new URL(url);
            // 打開鏈接
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            httpURLConnection.setRequestMethod("GET");
            // 經過BufferReader讀取數據
            InputStream iStream = httpURLConnection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(iStream);
            BufferedReader bReader = new BufferedReader(inputStreamReader);
            String temp = null;
            while ((temp = bReader.readLine()) != null) {
                sb.append(temp);
            }
            // 關閉流(先開後關,後開先關)
            bReader.close();
            inputStreamReader.close();
            iStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (httpURLConnection != null) {
                // 關閉鏈接
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
    }

}

 

 

struts.xml配置

 5.測試:

1.訪問:http://www.b.com/demo2/main.action

 

查看源碼:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="qlq">
<meta name="Keywords" content="">
<meta name="Description" content="單點登陸的界面">
<title>登陸界面</title>
</head>
<body>
    <center>
        <h3>請登陸</h3>
        <!-- 向當前本域提交登陸申請,處理登陸與cookie驗證在其它域處理 -->
        demo2
        <form action="/demo2/doLogin.action" method="post">
            用戶名:<input type="text" name="username" value="user" />
            &nbsp;&nbsp;&nbsp;&nbsp; 密碼:<input type="password" name="password"
                value="123" /> <input type="hidden" name="gotoUrl"
                value="http://www.b.com/demo2/main.action" /> <input type="submit" value="登陸" />
        </form>
    </center>
</body>
</html>

 

 

2.訪問:  http://www.a.com/demo1/main.action

 

查看源碼:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="qlq">
<meta name="Keywords" content="">
<meta name="Description" content="單點登陸的界面">
<title>登陸界面</title>
</head>
<body>
    <center>
        <h3>請登陸</h3>
        <!-- 向當前本域提交登陸申請,處理登陸與cookie驗證在其它域處理 -->
        demo1
        <form action="/demo1/doLogin.action" method="post">
            用戶名:<input type="text" name="username" value="user" />
            &nbsp;&nbsp;&nbsp;&nbsp; 密碼:<input type="password" name="password"
                value="123" /> <input type="hidden" name="gotoUrl"
                value="http://www.a.com/demo1/main.action" /> <input type="submit" value="登陸" />
        </form>
    </center>
</body>
</html>

 

3.登陸demo1

 

4.刷新demo2

相關文章
相關標籤/搜索