单点登录解决方案CAS

#单点登录解决方案CAS

##一、单点登录

​ 单点登录SSO,实现跨域登录。当用户第一次访问系统的时候,会被引导进入认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据service tikiet;在用户访问其他业务或者说下次访问的时候,客户端就会带上当前的凭据,服务端通过当前cookie中所携带的service tikiet进行验证,判断该用户是否登录。

###1.1 同域下的单点登录

​ 首先从传统的登录验证方式来看:

image

​ 如上图所示,我们在浏览器(Browser)中访问一个应用,这个应用需要登录,我们填写完用户名和密码后,完成登录认证。这时,我们在这个用户的session中标记登录状态为yes(已登录),同时在浏览器(Browser)中写入Cookie,这个Cookie是这个用户的唯一标识。下次我们再访问这个应用的时候,请求中会带上这个Cookie,服务端会根据这个Cookie找到对应的session,通过session来判断这个用户是否登录。如果不做特殊配置,这个Cookie的名字叫做jsessionid,值在服务端(server)是唯一的。

​ 同域下的单点登录主要针对同级域名下的所有系统,例如www.sso.a.com ,www.app1.a.com,www.app2.a.com。在同域下实现单点登录:首先要考虑seesion的存储,其次是seesion的共享问题;

image

第一步,将sso存储的cookie域设置为顶级域,如何设置呢?

​ 如果想所有a.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数

Cookie cookie = new Cookie(); // 新建Cookie
cookie.setDomain(".a.com"); // 设置域名

这样app1和app2就能够使用顶级域的cookie信息,但是seesion是存在于不同应用下,是不能够共享的。

###1.2 跨域单点登录

​ 跨域下的单点登录是指,在不同URL地址,两者属于不用的服务器。不同域之间Cookie是不共享的,,就无法通过cookie的来实现登录验证。

​ 下面通过对CAS官网的时序图解析进一步完成对跨域cas的认识和理解:

cas_flow_diagram

时序图流程解析:

​ 1、user通过浏览器发出get请求,请求app服务,但是此时用在没有登录。

​ 2、跳转到CAS server,即SSO登录系统,以后图中的CAS Server我们统一叫做SSO系统。 SSO系统也没有登录,弹出用户登录页。

​ 3、用户在登录页填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。

​ 4、SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。

​ 5、app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。

​ 6、验证通过后,app系统将登录状态写入session并设置app域下的Cookie。

至此,跨域单点登录就完成了。以后我们再访问app系统时,app就是登录的。接下来,我们再看看访问app2系统时的流程。

  1. 用户访问app2系统,app2系统没有登录,跳转到SSO。
  2. 由于SSO已经登录了,不需要重新登录认证。
  3. SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
  4. app2拿到ST,后台访问SSO,验证ST是否有效。
  5. 验证成功后,app2将登录状态写入session,并在app2域下写入Cookie

##二、CAS

###1、客户端开发

####1.1.原生方式

​ 通过web.xml方式进行配置

1.jar包依赖

   <dependencies>
        <dependency>
            <groupId>org.jasig.cas.client</groupId>
            <artifactId>cas-client-core</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

2.web.xml 配置文件解析

    <!-- ===================单点登录 ============================-->
    <!--=用于单点登出,该过滤器用于实现单点登出功能,可选择配置-->
     <listener>
          <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
      </listener>

      &lt;!&ndash; 该过滤器用于实现单点登出功能,可选配置&ndash;&gt;
      <filter>
          <filter-name>CAS Single Sign Out Filter</filter-name>
          <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>CAS Single Sign Out Filter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

      &lt;!&ndash;该过滤器负责用户的认证工作,必须配置&ndash;&gt;
      <filter>
          <filter-name>CASFilter</filter-name>
          <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
          <init-param>
              <param-name>casServerLoginUrl</param-name>
              <param-value>http://localhost:8080/cas/login</param-value>
              &lt;!&ndash;cas的服务端ip&ndash;&gt;
          </init-param>
          <init-param>
              <param-name>serverName</param-name>
              <param-value>http://localhost:9001</param-value>
          </init-param>
      </filter>
      <filter-mapping>
          <filter-name>CASFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

      &lt;!&ndash;该过滤器负责对ticket的校验工作,必须配置&ndash;&gt;
      <filter>
          <filter-name>CAS Validation Filter</filter-name>
          <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
          <init-param>
              <param-name>casServerUrlPrefix</param-name>
              <param-value>http://localhost:8080/cas/</param-value>
          </init-param>
          <init-param>
              <param-name>serverName</param-name>
              <param-value>http://localhost:9001</param-value>
          </init-param>
      </filter>
      <filter-mapping>
          <filter-name>CAS Validation Filter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

      &lt;!&ndash;该过滤器负责实现httpServletRequst请求的包裹,例如开发者需要通过httpServletRequst的getRemoteUser()方法获取登录的用户名&ndash;&gt;
      <filter>
          <filter-name>CAS httpServletRequst Wrapper Filter</filter-name>
          <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>CAS httpServletRequst Wrapper Filter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>-->

//当通过浏览器访问该地址的所有资源时,进行登录验证,进入>http://localhost:8080/cas,完成登录之后,可正常访问所有当前项目下的资源。

####1.2 spring Sercurity整合cas

配置文件: web.xml spring-sercurity.xml cas.properties

​ 1. jar包依赖

    <packaging>war</packaging>
    <properties>
        <spring.version>5.0.5.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring.version}</version>
        </dependency>        
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-cas</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jasig.cas.client</groupId>
            <artifactId>cas-client-core</artifactId>
            <version>3.3.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>log4j-over-slf4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定端口 -->
                    <port>9003</port>
                    <!-- 请求路径 -->
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>

​ 2. web.xml—配置Sercurity过滤器

   <!--spring Security整合-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-security.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

​ 3. spring-sercurity.xml ---- 配置spring-sercurity和cas

 <!--   entry-point-ref  入口点引用 -->
    <http  use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
        <intercept-url pattern="/login/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/**" access="ROLE_USER"/>
        <csrf disabled="true"/>
        <!-- custom-filter为过滤器, position 表示将过滤器放在指定的位置上,before表示放在指定位置之前  ,after表示放在指定的位置之后  -->
        <custom-filter ref="casAuthenticationFilter"  position="CAS_FILTER" />
        <custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
        <custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
    </http>

    <!-- CAS入口点 开始 -->
    <beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
        <!-- 单点登录服务器登录URL -->
        <beans:property name="loginUrl" value="${cas_url}/login"/>
        <beans:property name="serviceProperties" ref="serviceProperties"/>
    </beans:bean>
    <beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
        <!--service 配置自身工程的根地址+/login/cas   -->
        <beans:property name="service" value="${service_url}/login/cas"/>
    </beans:bean>
    <!-- CAS入口点 结束 -->

    <!-- 认证过滤器 开始 -->
    <beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
        <beans:property name="authenticationManager" ref="authenticationManager"/>
    </beans:bean>
    <!-- 认证管理器 -->
    <authentication-manager alias="authenticationManager">
        <authentication-provider  ref="casAuthenticationProvider">
        </authentication-provider>
    </authentication-manager>
    <!-- 认证提供者 -->
    <beans:bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
        <beans:property name="authenticationUserDetailsService">
            <beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                <beans:constructor-arg ref="userDetailsService" />
            </beans:bean>
        </beans:property>
        <beans:property name="serviceProperties" ref="serviceProperties"/>
        <!-- ticketValidator 为票据验证器 -->
        <beans:property name="ticketValidator">
            <beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                <beans:constructor-arg index="0" value="${cas_url}"/>
            </beans:bean>
        </beans:property>
        <beans:property name="key" value="an_id_for_this_auth_provider_only"/>
    </beans:bean>
    <!-- 认证类 -->
    <beans:bean id="userDetailsService" class="com.qingcheng.service.UserDetailServiceImpl"/>

    <!-- 认证过滤器 结束 -->

    <!-- 单点登出  开始  -->
    <beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
    <beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <beans:constructor-arg value="${cas_url}/logout?service=${service_url}"/>
        <beans:constructor-arg>
            <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
        </beans:constructor-arg>
        <beans:property name="filterProcessesUrl" value="/logout/cas"/>
    </beans:bean>
    <!-- 单点登出  结束 -->
详细解析: 
  • use-expressions="false"是否开启spel表达式,springEl表达式。
  • entry-point-ref=“casProcessingFilterEntryPoint” 切入点设置,如果需要加载第三方接口,在使用了第三方认证接口之后,需要在后面进行改接口的bean配置。
  • custom-filter ref=“casAuthenticationFilter” position=“CAS_FILTER” cas认证过滤器,CAS_FILTER是spring-security原有的过利器,通过potion属性指定位置,替换原有的过滤器。
  • custom-filter ref=“requestSingleLogoutFilter” before=“LOGOUT_FILTER” 请求单点退出过滤器。before,在XX之前,在LOGOUT_FILTER过滤器之前加上请求单点退出过滤器。
  • singleLogoutFilter 单点退出过滤器。
  • CAS入口点:
    • loginUrl 配置cas的入口地址,也叫作CAS server用户凭证地址。
    • serviceProperties 配置web服务器地址(项目地址),通过该值在CAS serve上生成service ticket。
  • casAuthenticationFilter 指定认证提供者 ——> authenticationManager 指定认证管理器 ——> 指定认证提供者 。
  • userDatailsService 用户授权接口。
  • ticketValidator 票据校验器,是cs提供的一个校验器。需要提供一个cas的url地址。
  • singleLogoutFilter cas提供的单点登出过滤器。
  • requestSingleLogoutFilter spring提供的请求单点登出过滤器,通过该过滤器请求所指向的url地址,简单来说就是完成了一个url的映射功能,将web服务的登出功能url地址映射到cas的登出过滤器url地址。

​ 4. cas.properties配置文件,配置cas的相关url地址

cas_url=http://localhost:8080/cas
service_url=http://localhost:9001

2、 CAS服务端配置

1. 认识cas文件结构和基本配置

编译后的class文件夹结构:

* 静态资源(js,css)存放目录为WEB-INF\classes\static 
  *  WEB-INF\classes\static 目录下存在本身的原有js、css样式,可以进行替换。同时也可以在 WEB-INF\classes\static\themes目录下新建自己的风格,
* html资源(thymeleaf模板)存放目录为WEB-INF\classes\templates 
* 主题配置文件存放在WEB-INF\classes,并且命名为[theme_name].properties 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RjY9abBh-1611042125678)(C:\Users\chens\Documents\HwShare\capture_20190701165351112.bmp)]

更多笔记查看

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值