• 单点登录前奏


    1.单点登录认识及环境搭建

    1.单点登录(Single Sign On)

    简称SSO。定义是在多个应用系统中,用户只需要登录一次就可以访问所有互相信任的应用系统。一般用于公司内部产品或某个产品系列的所有子系统中。比如公司的oa系统、icode系统、邮箱系统等等;再比如豆瓣系列的豆瓣FM、豆瓣读书、豆瓣电影、豆瓣日记等等,只需要登录一次,访问其他系统就没有必要再登录了。

    背景:

    1. 公司内部现存系统较多,各个系统分布在不同服务器上,用户使用过程中需要多次重复登陆,使用麻烦
    2. 各系统实现技术不相同,但都是基于Web,客户端语言可以是非java语言
    3. 各个系统用户数据不尽相同,缺乏统一管理,用户需要维护多套密码,管理员也需要维护多套用户信息
    4. SSO服务端仅负责认证,权限管理可以交由各系统自己完成

    想了解更多单点登录原理进入单点登录原理与简单实现【转】

    2.创建证书

    证书是单点登录认证系统中很重要的一把钥匙,客户端与服务器的交互安全靠的就是证书;本次由于是演示所以就用JDK自带的keytool工具生成证书;如果以后真正在产品环境中使用肯定要去证书提供商去购买,证书认证一般都是由VeriSign认证,中文网站:http://www.verisign.com/cn/

    JDK自带的keytool工具生成证书过程如下:
    注意:以管理员的身份打开cmd

    1.生成证书

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

    需要设置密码:这里设置成123456

    注:www.wp.com是域名,以后配置CAS客户端时需要用到且必须一致。

    2.导出证书

        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 FilesJavajdk1.8.0_131jrelibsecurity/cacerts"
    

    密码是默认的changeit,而不是之前设置的密码。
    https://www.cnblogs.com/hamfy/archive/2012/07/31/2616805.html

    4.其他命令
    查看证书列表

        keytool -list -v -keystore "D:Program FilesJavajdk1.8.0_131jrelibsecurity/cacerts"
    

    删除证书

        keytool -delete -trustcacerts -alias tomcat -keystore  "D:Program FilesJavajdk1.8.0_131jrelibsecurity/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.理解几个概念

    1、TGC (Ticket-granting cookie):存放用户身份认证凭证的cookie,在浏览器和SSO server之间通讯时使用,并且只能用HTTPS传输,说白了,就是你登陆SSO系统后,SSO server会在你的浏览器Cookie里面植入一段Cookie,这样在Cookie的有效期内你访问任何接入SSO的系统都不需要再次输入密码,只需要校验该Cookie的有效性,因为基于HTTPS传输,所以说能够保证传输过程中的安全性,但是注意保管你自己电脑的不被别人窃取该信息,不然别人就能伪造以你的身份登陆。也称为全局会话。
    查看你的cookie就能看到该信息,就是叫CASTGC的cookie,可以看到该cookie的有效期为浏览会话结束时。可以设置一个月时间。

    2、TGT(Ticket Granting ticket):票据授权票据。该票据存在Server端,其实TGC是TGT的id而已,在你完成认证后服务端生成TGT存起来,然后把TGT的id下发给用户保存在cookie中,这样下次用户来就可以通过TGC找到TGT,然后校验该TGT的一系列信息,认证通过就可以免密码登录。

    3、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改造是很有必要了解的。

  • 相关阅读:
    EasyNVR播放HLS协议时ts文件报错404是什么问题?
    【操作步骤】EasyNVR硬件设备如何设置通电不自动启动?
    C#实现QQ接口软件QQ的HTTP接口协议探究
    第一篇随笔
    Extjs继承相关
    Montgomery乘法介绍
    中国商用密码杂凑算法标准SM3算法(数字签名)
    c语言链接动态库dll
    环、商环、整数环
    大数据挖掘技术及应用(复习重点)
  • 原文地址:https://www.cnblogs.com/zhanxiaoyun/p/8516199.html
Copyright © 2020-2023  润新知