• CAS单点登录实践(spring cas client配置)


    前言:

      最近的项目需要将多个站点统一登录,查阅了资料Jasig cas(Central Authentication Service)(官方站点:http://www.jasig.org/cas)使用的比较多。

    项目情况:

      开发语言:JAVA

      框架:spring

      容器:tomcat7

      JDK: 1.7

      部署方式:docker

    目标:

      实现OMS、BMS、UMS、VOD、Live多站点切换期间只有第一次访问的站点需要登录,登录后调转的其他站点不需要在登录。

    过程:

      在配置前需要开启tomcat的TLS功能,服务器端和客户端都要开启。(切记要讲证书导入jre中,遇到 IO.Exception时,可以将cacerts文件删除)。网上有些教程为了简化操作,使用了http,没有使用https。但是在http协议下,第一个站点登录后,第一次跳转到其他站点还是需要再次登录的。可以先用http搭建简单的cas服务器,单个网站可以调转过来后,再启用https。毕竟登录一次,到处访问才是我们用cas的目的。

    1、cas服务器端,参考站点《http://www.cnblogs.com/vhua/p/cas_1.html》

      1.1 解压下载的 cas-server-4.0.0-release.zip 压缩包

      1.2 找到 X:cas-server-4.0.0modulescas-server-webapp-4.0.0.war 文件

      1.3解压到 tomcat-caswebapps 下

      

    2、客户端站点配置:

      2.1 修改web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
      </listener>
      <display-name>vod_console</display-name>
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
                classpath:config/spring-mybatis.xml,classpath:config/spring-cas.xml
        </param-value>
        <!-- classpath:config/spring-security.xml -->
      </context-param>
      <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>vod_console.root</param-value>
      </context-param>
      <context-param>
            <param-name>spring.profiles.active</param-name>  
            <param-value>dev</param-value>  
        </context-param>  
        <context-param>  
            <param-name>spring.profiles.default</param-name>  
            <param-value>dev</param-value>  
        </context-param>
        <context-param>  
            <param-name>spring.liveBeansView.mbeanDomain</param-name>  
            <param-value>dev</param-value>  
        </context-param>
        <!-- 一定要在cas的前面 -->
        <filter>
        <filter-name>SetCharacterEncoding</filter-name>
        <filter-class>
                org.springframework.web.filter.CharacterEncodingFilter
            </filter-class>
        <init-param>
          <param-name>encoding</param-name>
          <param-value>UTF-8</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>SetCharacterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      
         <!--  单点登录开始  -->
     <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>
     
     <!-- 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 -->
        <listener>
            <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</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>
      <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:config/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
      <error-page>
        <error-code>403</error-code>
        <location>/403</location>
      </error-page>
      <error-page>
        <error-code>404</error-code>
        <location>/404</location>
      </error-page>
      <error-page>
        <error-code>500</error-code>
        <location>/500</location>
      </error-page>
      <listener>
        <listener-class>com.guttv.common.utils.ParamLoaderListener</listener-class>
      </listener>
    </web-app>

      注意:原来spring的字符过滤器,一定要在cas的过滤器后面,否则提交数据会出现中文乱码。这里参考了“next_door_body”的文章,《http://www.cnblogs.com/next-door-boy/p/3361328.html》,这里感谢next_door_body。

      2.2 创建spring-cas.xml文件,这个是参考了网站《https://wiki.jasig.org/display/casc/using+the+cas+client+3.1+with+spring+security》

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
        
        <bean id="propertyConfigurer2"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="order" value="2" />
            <property name="ignoreUnresolvablePlaceholders" value="true" />
            <property name="locations">
                <list>
                    <value>classpath:config/jdbc.properties</value>
                    <value>classpath:config/cas.properties</value>
                </list>
            </property>
        </bean>
        <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
            <sec:filter-chain-map path-type="ant">
                <sec:filter-chain pattern="/"
                    filters="casValidationFilter, wrappingFilter" />
                <sec:filter-chain pattern="/guttv" filters="casValidationFilter" />
                <sec:filter-chain pattern="/j_spring_security_logout"
                    filters="logoutFilter,etf,fsi" />
                <sec:filter-chain pattern="/**"
                    filters="casAuthenticationFilter, casValidationFilter, wrappingFilter, sif,j2eePreAuthFilter,logoutFilter,etf,fsi" />
            </sec:filter-chain-map>
        </bean>
    
        <bean id="sif"
            class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />
    
    
        <sec:authentication-manager alias="authenticationManager">
            <sec:authentication-provider ref="preAuthAuthProvider" />
        </sec:authentication-manager>
    
        <bean id="preAuthAuthProvider"
            class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
            <property name="preAuthenticatedUserDetailsService">
                <bean id="userDetailsServiceWrapper"
                    class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                    <property name="userDetailsService" ref="userService" />
                </bean>
            </property>
        </bean>
    
        <bean id="preAuthEntryPoint"
            class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
    
        <bean id="j2eePreAuthFilter"
            class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
            <property name="authenticationManager" ref="authenticationManager" />
            <property name="authenticationDetailsSource">
                <bean
                    class="org.springframework.security.web.authentication.WebAuthenticationDetailsSource" />
            </property>
        </bean>
    
        <bean id="logoutFilter"
            class="org.springframework.security.web.authentication.logout.LogoutFilter">
            <constructor-arg value="/" />
            <constructor-arg>
                <list>
                    <bean
                        class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
                </list>
            </constructor-arg>
        </bean>
    
        <bean id="servletContext"
            class="org.springframework.web.context.support.ServletContextFactoryBean" />
    
        <bean id="etf"
            class="org.springframework.security.web.access.ExceptionTranslationFilter">
            <property name="authenticationEntryPoint" ref="preAuthEntryPoint" />
        </bean>
    
        <bean id="httpRequestAccessDecisionManager"
            class="org.springframework.security.access.vote.AffirmativeBased">
            <property name="allowIfAllAbstainDecisions" value="false" />
            <property name="decisionVoters">
                <list>
                    <ref bean="roleVoter" />
                </list>
            </property>
        </bean>
    
        <bean id="fsi"
            class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
            <property name="authenticationManager" ref="authenticationManager" />
            <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager" />
            <property name="securityMetadataSource">
                <sec:filter-invocation-definition-source>
                    <sec:intercept-url pattern="/secure/extreme/**"
                        access="ROLE_SUPERVISOR" />
                    <sec:intercept-url pattern="/combo/**" access="ROLE_USER" />
                    <sec:intercept-url pattern="/**" access="ROLE_USER" />
                </sec:filter-invocation-definition-source>
            </property>
        </bean>
    
        <bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />
    
        <bean id="securityContextHolderAwareRequestFilter"
            class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter" />
    
        <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"
            id="ticketValidator">
            <constructor-arg index="0" value="${casServer}/cas" />
            <property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
            <property name="proxyCallbackUrl"
                value="${vod.localServer}/${vod.project}/category/tree/listRoot" />
    
        </bean>
    
        <bean id="proxyGrantingTicketStorage"
            class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
    
        <sec:user-service id="userService">
            <sec:user name="lzj999" password="1234" authorities="ROLE_SUPERVISOR,ROLE_USER" />
            <sec:user name="dianne" password="dianne" authorities="ROLE_USER" />
            <sec:user name="lzj" password="1234" authorities="ROLE_USER" />
        </sec:user-service>
    
        <bean id="casAuthenticationFilter"
            class="org.jasig.cas.client.authentication.AuthenticationFilter">
            <property name="casServerLoginUrl" value="${casServer}/cas/login" />
            <property name="serverName" value="${vod.localServer}" />
        </bean>
    
        <bean id="casValidationFilter"
            class="org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter">
            <property name="serverName" value="${vod.localServer}" />
            <property name="exceptionOnValidationFailure" value="true" />
            <property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
            <property name="redirectAfterValidation" value="true" />
            <property name="ticketValidator" ref="ticketValidator" />
            <property name="proxyReceptorUrl" value="/guttv" />
        </bean>
    
        <bean id="wrappingFilter"
            class="org.jasig.cas.client.util.HttpServletRequestWrapperFilter" />
    </beans>

       本文件中的相关参数都被提取到cas.properties文件中了,spring-cas.xml就比较通用了,参数也看得比较清晰。

    casServer=https://dev.guttv.com:8443
    oms.localServer = https://dev.guttv.com:9443
    oms.project = oms_console
    vod.localServer = https://dev.guttv.com:9443
    vod.project = vod_console

    2.3 登录用户名的获取:

      

    <%@ page import="org.jasig.cas.client.authentication.AttributePrincipal"%>
    
    <%
        /*CasAuthenticationToken casAuthenticationToken = (CasAuthenticationToken) SecurityContextHolder
                .getContext().getAuthentication();
        AttributePrincipal principal = casAuthenticationToken
                .getAssertion().getPrincipal();
        request.setAttribute("username", principal.getName());
         */
        AttributePrincipal principal = (AttributePrincipal) request
                .getUserPrincipal();
        String username = principal.getName();
        request.setAttribute("username", username);
        String password = principal.getProxyTicketFor(username);
        request.setAttribute("pwd", password);
    %>
    
    <c:when test="${not empty username }">
                            <li class="dropdown"><a href="#" class="dropdown-toggle"
                                data-toggle="dropdown" role="button" aria-expanded="true">你好:${username }
                                    <span class="caret"></span>
                            </a>
                                <ul class="dropdown-menu" role="menu">
                                    <li><a href="${context }/user/person">个人信息</a></li>
                                    <li class="divider"></li>
                                    <li><a href="${context }/static/j_spring_security_logout">退出</a></li>
                                </ul></li>
    
                        </c:when>
    org.jasig.cas.client.authentication.AttributePrincipal在cas-client-core-3.2.1.jar包里,这个包是Jasig提供的。
  • 相关阅读:
    c# 遍历DataTable
    c# 判断网络状态
    c# 发送Http 请求
    c# 处理Json字符串
    环境搭建(Nginx + PHP7 + Mysql + 运行ThinkPHP5项目)
    c# 获取时间戳
    php 处理 byte
    微信小程序 滚动至元素底部
    mysql 删除 多个字段相同的 重复的 数据
    微信小程序 跑马灯效果
  • 原文地址:https://www.cnblogs.com/liughost/p/4846446.html
Copyright © 2020-2023  润新知