CAS单点登录实现案例

我们先按套路来,上点客套的:

1、CAS的基本工作原理

094735_0edq_697871.png

2、CAS的时序图如下

094829_qx6O_697871.png

3、好吧好吧,下面废话不说,我直接来干货

A、hosts文件的配置,可有可无,但是按照我之前看别人的博客,这个还是方便安全证书的生成的

    C:\Windows\System32\drivers\etc\hosts 文件中添加三条

        127.0.0.1 demo.tch.com

        127.0.0.1 app1.tch.com

        127.0.0.1 app2.tch.com

        demo.tch.com =>>对应部署cas server的tomcat,这个虚拟域名还用于证书生成
        app1.tch.com =>> 对应部署app1的tomcat
        app2.tch.com =>>对应部署app2的tomcat

B、生成安全证书

C:\Users\yang>keytool -genkey -alias ssodemo1 -keyalg RSA -keysize 1024 -keypass 123456 -keystore 
 f:\sso\ssodemo.keystore -storepass 123456

keypass 和 storepass 两个密码要一致,否则下面tomcat 配置https 访问失败;

然后我们将证书导出:

C:\Users\yang>keytool -export -alias ssodemo1 -keystore f:\sso\ssodemo.keystore -file 
 f:\sso\ssodemo.crt -storepass 123456

 

有关keytool工具的详细运用见:http://www.micmiu.com/lang/java/keytool-start-guide/

C、进行服务端的配置,这个比较重要,而且也是浪费我时间最多的一个地方,因为网上的博客很多东西写的都不对,我也不知道他们是怎么实现的,我把我的弯路show给你看:

服务端tomcat配置文件 conf/server.xml文件进行如下修改:

 <Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" />

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               keystoreFile="F:/Study/Java/Projects/SSO/Demo/keys/ssodemo.keystore" keystorePass="123456"
               clientAuth="false" sslProtocol="TLS" URIEncoding="UTF-8"/>
	
    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

 <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
             resourceName="UserDatabase"/>

 <Host name="demo.tch.com"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">

对以上代码进行截图,然后对以上配置进行分析

101023_YMql_697871.png

CAS-Server下载地址:http://www.jasig.org/cas/download

本文以cas-server-3.4.11-release.zip为例,解压提取cas-server-3.4.11/modules/cas-server-webapp-3.4.11.war文件,把改文件copy到 G:\sso\tomcat-cas\webapps\目下,并重命名为:cas.war.

启动tomcat-cas,在浏览器地址栏输入:https://demo.tch.com:8443/cas/login ,回车

133119_5E5P_697871.png

写这篇日志的时候,很多东西我都已经修改了,但是以上表示成功了,真实的图片容我给你盗个图来

101504_B57V_697871.png

CAS-server的默认验证规则:只要用户名和密码相同就认证通过(仅仅用于测试,生成环境需要根据实际情况修改),输入admin/admin 点击登录,就可以看到登录成功的页面:

101558_3Imw_697871.png

看到上述页面表示CAS-Server已经部署成功。

上面的初体验仅仅是简单的身份验证,实际应用中肯定是要读取数据库的数据,下面我们来进一步配置CAS服务器怎么读取数据库的信息进行身份验证。 首先打开

cas/WEB-INF/deployerConfigContext.xml

注释掉:SimpleTestUsernamePasswordAuthenticationHandler这个验证Handler,这个是比较简单的,只是判断用户名和密码相同即可通过,这个肯定不能在实际应用中使用,弃用!紧接着添加如下代码

<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
    <property name="dataSource" ref="dataSource"></property>
    <property name="sql" value="select password from t_admin_user where login_name=?"></property>
    <property name="passwordEncoder" ref="MD5PasswordEncoder"></property>
</bean>

在文件的末尾之前加入如下代码:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
   <property name="url"><value>jdbc:mysql:///wsriademo</value></property>
   <property name="username"><value>root</value></property>
   <property name="password"><value>root</value></property>
</bean>
 
<bean id="MD5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">
    <constructor-arg index="0">
        <value>MD5</value>
    </constructor-arg>
</bean>

复制cas-server-3.4.3.1\modules\cas-server-support-jdbc-3.4.3.1.jar和mysql/Oracle驱动jar包到tomcat/webapp/cas/WEB-INF/lib目录

  • QueryDatabaseAuthenticationHandler,是cas-server-support-jdbc提供的查询接口其中一个,QueryDatabaseAuthenticationHandler是通过配置一个 SQL 语句查出密码,与所给密码匹配

  • dataSource,我就不用解释了吧,就是使用JDBC查询时的数据源

  • sql,语句就是查询哪一张表,本例根据t_admin_user表的login_name字段查询密码,CAS会匹配用户输入的密码,如果匹配则通过

  • passwordEncoder,这个就算是自己加的盐巴了,意思很明显就是处理密码的加密,看你的应用中数据库保存的是明码还是加密过的,比如本例是使用MD5加密的,所以配置了MD5PasswordEncoder这个Handler,cas内置了MD5的功能所以只需要配置一下就可以了;如果在实际应用中使用的是公司自己的加密算法那么就需要自己写一个Handler来处理密码,实现方式也比较简单,创建一个类继承org.jasig.cas.authentication.handler.PasswordEncoder然后在encode方法中加密用户输入的密码然后返回即可.

然后修改cas/WEB-INF/cas.properties文件,修改如下两行,具体含义我就不多说了

server.name=http://demo.tch.com:8080
server.prefix=${server.name}/cas

D、客户端的配置

导入jar包

<dependency>
    <groupid>org.jasig.cas.client</groupid>
    <artifactid>cas-client-core</artifactid>
    <version>3.1.12</version>
</dependency>

修改你客户端中的web.xml文件进行修改,添加filter

   <!-- sso 单点登录sso 单点登录sso 单点登录sso 单点登录sso 单点登录sso 单点登录sso 单点登录-->
    <listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>
    <!--该过滤器用于实现单点登出功能,可选配置。-->
    <!--<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>CASFilter</filter-name>
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>http://demo.tch.com:8080/cas/login</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://app1.tch.com:18080</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CASFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--该过滤器负责对Ticket的校验工作,必须启用它-->
    <filter>
        <filter-name>CASValidationFilter</filter-name>
        <filter-class>
            org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>http://demo.tch.com:8080/cas</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://app1.tch.com:18080</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CASValidationFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--
                            该过滤器负责实现HttpServletRequest请求的包裹,
                            比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。
                    -->
    <filter>
        <filter-name>CASHttpServletRequest WrapperFilter</filter-name>
        <filter-class>
            org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CASHttpServletRequest WrapperFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--
                    该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
                    比如AssertionHolder.getAssertion().getPrincipal().getName()。
                    -->
    <filter>
        <filter-name>CASAssertion Thread LocalFilter</filter-name>
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CASAssertion Thread LocalFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

注*此时app1的http端口号为1880,通过拦截来跳转到cas服务,cas服务通过了用户名和密码之后携带cas生成的tickets回到客户端。

在app1系统的intercepter拦截器中,根据AssertionHolder.getAssertion().getPrincipal().getName()取得当前登录用户的用户名,来从自己的系统数据库中取得用户信息。同时在单独登录系统时,也不会受到cas系统干扰。

User user = (User) session.getAttribute("admin");
        if(null == user){
            if(null != AssertionHolder.getAssertion()){
                String userName = AssertionHolder.getAssertion().getPrincipal().getName();
                if(null != userName || !"".equals(userName)){
                    user = userService.queryUserByuserName(userName);
                }
            }
        }

E、预期流程:打开app1 url —->跳转cas server验证 —->显示app1的应用 —->打开app2 url —->显示app2应用 —->注销cas server —->打开app1/app2url —->重新跳转到cas server验证.

F、

CAS服务端(cas-server)的界面只能在测试的时候用一下,真正系统上线肯定需要定制开发自己的页面,就像网易CSDN的统一认证平台一样,所有子系统的认证都通过此平台来转接,大家可以根据他们的页面自己定制出适合所属应用或者公司的界面;简单介绍一下吧,复制 cas\WEB-INF\view\jsp\default\ui的一些JSP文件,每一个文件的用途文件名已经区分了,自己修改了替换一下就可以了。 例如:

  • 登录界面:casLoginView.jsp
  • 登录成功:casGenericSuccess.jsp
  • 登出界面:casLogoutView.jsp

 

 

参考资料:http://www.2cto.com/os/201402/281465.html

                http://www.kafeitu.me/sso/2010/11/05/sso-cas-full-course.html

 

转载于:https://my.oschina.net/ytliyang/blog/795270

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值