單點登陸前奏

1.單點登陸認識及環境搭建

1.單點登陸(Single Sign On)

簡稱SSO。定義是在多個應用系統中,用戶只須要登陸一次就能夠訪問全部互相信任的應用系統。通常用於公司內部產品或某個產品系列的全部子系統中。好比公司的oa系統、icode系統、郵箱系統等等;再好比豆瓣系列的豆瓣FM、豆瓣讀書、豆瓣電影、豆瓣日記等等,只須要登陸一次,訪問其餘系統就沒有必要再登陸了。html

背景:java

  1. 公司內部現存系統較多,各個系統分佈在不一樣服務器上,用戶使用過程當中須要屢次重複登錄,使用麻煩
  2. 各系統實現技術不相同,但都是基於Web,客戶端語言能夠是非java語言
  3. 各個系統用戶數據不盡相同,缺少統一管理,用戶須要維護多套密碼,管理員也須要維護多套用戶信息
  4. SSO服務端僅負責認證,權限管理能夠交由各系統本身完成

想了解更多單點登陸原理進入單點登陸原理與簡單實現【轉】web

2.建立證書

證書是單點登陸認證系統中很重要的一把鑰匙,客戶端與服務器的交互安全靠的就是證書;本次因爲是演示因此就用JDK自帶的keytool工具生成證書;若是之後真正在產品環境中使用確定要去證書提供商去購買,證書認證通常都是由VeriSign認證,中文網站:http://www.verisign.com/cn/spring

JDK自帶的keytool工具生成證書過程以下:
注意:以管理員的身份打開cmd數據庫

1.生成證書apache

keytool -genkey -alias tomcat -keyalg RSA -keystore D:/software/keys/keystore

須要設置密碼:這裏設置成123456
瀏覽器

注:www.wp.com是域名,之後配置CAS客戶端時須要用到且必須一致。緩存

2.導出證書tomcat

keytool -export -trustcacerts -alias tomcat -file D:/software/keys/tomcat.cer -keystore D:/software/keys/keystore

3.將證書導入JDK信任庫安全

keytool -import -trustcacerts -alias tomcat -file D:/software/keys/tomcat.cer -keystore "D:\Program Files\Java\jdk1.8.0_131\jre\lib\security/cacerts"

密碼是默認的changeit,而不是以前設置的密碼。
https://www.cnblogs.com/hamfy/archive/2012/07/31/2616805.html

4.其餘命令
查看證書列表

keytool -list -v -keystore "D:\Program Files\Java\jdk1.8.0_131\jre\lib\security/cacerts"

刪除證書

keytool -delete -trustcacerts -alias tomcat -keystore  "D:\Program Files\Java\jdk1.8.0_131\jre\lib\security/cacerts"

3.Tomcat配置

啓用We服務器的SSL,也就是HTTPS加密協議。
配置tomcat的server.xml

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="D:/software/keys/keystore"
               keystorePass="123456" />

keystoreFile:建立的key存放的位置
keystorePass:建立證書時的密碼

4. 配置www.wp.com域名指向本地


編輯host文件,添加下面內容,保存便可。

5.啓動tomcat,瀏覽器輸入https:www.wp.com:8443/ 是否正常訪問

若是正常訪問到該地址,那麼表示配置成功。

若還不能訪問,則在server.xml中將下面內容註釋掉。

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

2.單點登陸實現

1.服務端cas-server

下載cas-server-3.5.0-release
https://www.apereo.org/projects/cas/news
下載完成後解壓,並更名爲cas,複製到tomcat/webapp目錄下,啓動tomcat,並訪問地址:
https:www.wp.com:8443/cas/login 用戶名/密碼:admin/admin點擊登陸。cas默認的驗證規則是隻要用戶名和密碼相同就能夠經過。

2.客戶端

新建springboot web項目,使用maven管理jar包,pom.xml文件加入包

<dependencies>
    <!--web應用基本環境配置 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.jasig.cas.client</groupId>
        <artifactId>cas-client-core</artifactId>
        <version>${cas.version}</version>
    </dependency>
</dependencies>

application.yaml配置文件

server:
  port: 8081
spring:
  profiles:
    active: dev

---
# 開發環境配置
spring:
  profiles: dev
cas:
  casServerUrlPrefix: https://www.wp.com:8443/cas
  casServerLoginUrl: https://www.wp.com:8443/cas/login
  serverName: http://localhost:8081
  encoding: UTF-8
  urlPatterns: /*

新建一個配置類,配置單點登陸客戶端過濾器CasConfig

package com.baidu.bpit.uuap.conf;

import org.jasig.cas.client.authentication.AuthenticationFilter;
import org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
@ConfigurationProperties(prefix = "cas", ignoreUnknownFields = true)
public class CasConfig {

    private String casServerUrlPrefix;  // sso驗證地址
    private String casServerLoginUrl;   // sso登陸地址
    private String serverName;  // sso驗證或者登錄後返回的地址
    private String urlPatterns; // sso過濾匹配
    private String encoding;    // sso編碼

    /**
     * 註冊CAS SSO 驗證用戶是否存在Filter
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean cas20ValidateRegistration() {
        FilterRegistrationBean cas20 = new FilterRegistrationBean();
        cas20.setFilter(new Cas20ProxyReceivingTicketValidationFilter());
        cas20.addUrlPatterns(urlPatterns);
        cas20.addInitParameter("casServerUrlPrefix", casServerUrlPrefix);
        cas20.addInitParameter("serverName", serverName);
        cas20.addInitParameter("encoding", encoding);
        return cas20;
    }

    /**
     * 註冊CAS SSO 用戶登陸Filter
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean cas20LoginRegistration() {
        FilterRegistrationBean cas20 = new FilterRegistrationBean();
        cas20.setFilter(new AuthenticationFilter());
        cas20.addUrlPatterns(urlPatterns);
        cas20.addInitParameter("casServerLoginUrl", casServerLoginUrl);
        cas20.addInitParameter("serverName", serverName);
        cas20.addInitParameter("encoding", encoding);
        return cas20;
    }

    public String getCasServerUrlPrefix() {
        return casServerUrlPrefix;
    }

    public void setCasServerUrlPrefix(String casServerUrlPrefix) {
        this.casServerUrlPrefix = casServerUrlPrefix;
    }

    public String getCasServerLoginUrl() {
        return casServerLoginUrl;
    }

    public void setCasServerLoginUrl(String casServerLoginUrl) {
        this.casServerLoginUrl = casServerLoginUrl;
    }

    public String getServerName() {
        return serverName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    public String getUrlPatterns() {
        return urlPatterns;
    }

    public void setUrlPatterns(String urlPatterns) {
        this.urlPatterns = urlPatterns;
    }

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }
}

建立訪問首頁controller,獲取到session中的用戶心

@ResponseBody
@RequestMapping("/demo")
public String getLoginUser(HttpServletRequest httpServletRequest) {

    // 獲取session裏面的用戶信息
    HttpSession session = httpServletRequest.getSession();
    String userName = "-";
    if (null != session) {
        Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
        if (null != assertion) {
            userName = assertion.getPrincipal().getName();
        }
    }
    logger.info("get current user: {}", userName);
    return "Welcome you : " + "demo2";
}

而後啓動項目,瀏覽器訪問http://localhost:8081/demo

輸入用戶名和密碼,回車

3.單點登陸流程解析

1.理解幾個概念

一、TGC (Ticket-granting cookie):存放用戶身份認證憑證的cookie,在瀏覽器和SSO server之間通信時使用,而且只能用HTTPS傳輸,說白了,就是你登錄SSO系統後,SSO server會在你的瀏覽器Cookie裏面植入一段Cookie,這樣在Cookie的有效期內你訪問任何接入SSO的系統都不須要再次輸入密碼,只須要校驗該Cookie的有效性,由於基於HTTPS傳輸,因此說可以保證傳輸過程當中的安全性,可是注意保管你本身電腦的不被別人竊取該信息,否則別人就能僞造以你的身份登錄。也稱爲全局會話。
查看你的cookie就能看到該信息,就是叫CASTGC的cookie,能夠看到該cookie的有效期爲瀏覽會話結束時。能夠設置一個月時間。

二、TGT(Ticket Granting ticket):票據受權票據。該票據存在Server端,其實TGC是TGT的id而已,在你完成認證後服務端生成TGT存起來,而後把TGT的id下發給用戶保存在cookie中,這樣下次用戶來就能夠經過TGC找到TGT,而後校驗該TGT的一系列信息,認證經過就能夠免密碼登陸。

三、ST(Service Ticket):這個ST即是瀏覽器中的ticket參數,sso認證經過後攜帶該參數讓用戶重定向到下游系統,下游系統拿到該參數便去sso server驗證該參數的有效性,經過驗證即可以讓用戶進入下游系統。

怎樣才能保證ticket參數的安全性呢?

(1)、https傳輸。
(2)、ticket只能使用一次,無論認證成功或者失敗
(3)、ticket有有效期,默認5分鐘
(4)、ticket是隨機生成的,具備不可僞造性

2.流程圖及流程解析

單點登陸經常使用的操做有三個:login、serviceValidate、logout,最複雜的就是login接口。
單點登陸服務端使用spring-webflow技術實現了單點登陸的login流程,整理login邏輯流程圖以下:

1.用戶訪問系統1的受保護資源,系統1發現用戶未登陸,跳轉到SSO認證中心,並將用戶訪問系統1的地址做爲參數傳遞過去
2.SSO認證中心接收到請求後,走login-webflow流程,配置信息在cas-servlet.xml中,

首先會進入初始化操做流程 initialFlowSetupAction,執行初始化數據等操做。
而後響應給瀏覽器casLoginView.jsp頁面
用戶提交用戶名和密碼後去SSO認證中心校驗
校驗success後,去生成全局會話,將id保存到cookie中;sendTicketGrantingTicketAction
而後去建立系統1的受權令牌ticket;generateServiceTicketAction
最後,SSO以以前傳過來的參數地址爲地址而且拼接ticket參數,重定向到系統1中。

系統1拿到ticket參數後,去SSO認證中心校驗ticket的有效性,有效,再重定向到系統1,系統1會創建用戶和系統1的局部會話,證實用戶是否登陸系統1,最後返回系統1訪問的資源。
注意:全局會話TGT的id TGC保存在cookie中CASTGC;若該cookie存在,那麼其餘客戶端也是登陸狀態,不會再驗證用戶密碼信息了,而後生成新的ticket。
ticket完成客戶端service在SSO認證中心的校驗。

cas client、cas server、瀏覽器之間的流程

在圖中第3步用戶認證成功後,cas server會生成Ticket Granting Ticket(票據受權票據,簡稱TGT),同時將TGT值以CASTGC爲名保存到瀏覽器的cookie中,以後生成Service Ticket(服務票據,簡稱ST)並緩存,在第4步時將ST經過瀏覽器重定向的URL傳給cas client。

當客戶訪問另外一個cas client時,一樣會被重定向到cas server,而此時咱們並不但願再次讓用戶輸入用戶密碼登錄,名爲CASTGC的cookie這時就體現出做用來了,cas server發現存在名爲CASTGC的cookie就將其值在已保存的TGT中查找,若存在,則說明已存在合法的TGT,cas server就根據該TGT生成新的ST,接下來的流程就和之前同樣了。

固然,在實際產品中不能直接使用從官網下載下來的cas-server,須要對其進行相關的改造,好比登錄頁面須要改爲體現產品特點的,添加驗證碼,用戶登陸信息驗證方案,TGT、serviceTicket緩存方案和持久化到數據庫、加入域登陸等等諸多地方。那麼下一篇單點登陸cas-server改造是頗有必要了解的。

相關文章
相關標籤/搜索