CAS单点登陆基本使用

1.单点登陆简介

单点登陆(single Sign On),简称SSO。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。传统方式登陆信息是存储在session中,而session是存储在服务器中,但在分布式系统中存在很多子系统,他们有各自的服务器,显然使用session无法解决问题。

2.CAS介绍

CAS是一个解决单点登陆的技术,旨在为 Web 应用系统提供一种可靠的单点登录方法,它的特点是:1开源,2CAS Server为需要独立部署的web应用,3CAS Client 支持非常多的客户端(这里指需要登陆的web应用),Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。

3.单点登陆实现步骤

1.浏览器发送请求访问应用系统

2.应用系统重定向到单点登陆服务端

3.用户认证

4.发送票据,用户认证完后单点登陆服务端会返回一个ticket

5.浏览器获取到ticket后会将ticket发送给应用系统

6.应用系统将ticket发送给单点登陆服务器进行验证,获取用户信息

4.CAS服务端部署和配置

1.下载cas服务端war工程(https://www.apereo.org/projects/cas/download-cas),使用tomcat运行,输入http://localhost:8880/cas,如下结果:

输入用户名:casuser,密码:Mellon登录,如果不想使用默认用户名密码登陆可以修改cas工程中WEB-INF中deployerConfigContext.xml文件:

<bean id="primaryAuthenticationHandler"
          class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
        <property name="users">
            <map>
                <entry key="casuser" value="Mellon"/>
            </map>
        </property>
    </bean>

2.cas服务端配置

1)如果不想使用tomcat默认端口,修改server.xml文件,同时要修改cas工程中WEB-INF中cas.properties文件中的server.name

2)去除https认证

        CAS 默认使用的是 HTTPS 协议,如果使用 HTTPS 协议需要 SSL 安全证书(需向特定的机构申请和购买)。这里修改使用http协议。步骤如下:

  1. 修改cas工程中WEB-INF中deployerConfigContext.xml文件,找到如下配置:
    <!-- Required for proxy ticket mechanism. -->
        <bean id="proxyAuthenticationHandler"
              class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
              p:httpClient-ref="httpClient" />

     加入属性:p:requireSecure="false",requireSecure的意思是是否需要安全验证,这里为false即不采用安全验证,启用http协议。

  2. 修改 cas 的/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml,这个文件是和ticket有关,
<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
		p:cookieSecure="true"
		p:cookieMaxAge="-1"
		p:cookieName="CASTGC"
		p:cookiePath="/cas" />

将p:cookieSecure="true"改为p:cookieSecure="false",同样的true为https验证,false为不采用https验证。

参数 p:cookieMaxAge="-1"的意思是Cookie的最大生命周期,为-1即无生命周期,浏览器不存储Cookie,当关闭浏览器后需要重新登陆。当设置参数为60时即生命周为60秒,在60秒内打开任意窗口都不需要验证。

3.修改 cas 的 WEB-INF/spring-configuration/warnCookieGenerator.xml

<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
		p:cookieSecure="true"
		p:cookieMaxAge="-1"
		p:cookieName="CASPRIVACY"
		p:cookiePath="/cas" />

修改p:cookieSecure="true"为p:cookieSecure="false",设置p:cookieMaxAge="600"。

3.cas客户端搭建

1)新建Meven工程(war),加入cas依赖:

<dependency>  
	<groupId>org.jasig.cas.client</groupId>  
	<artifactId>cas-client-core</artifactId>  
	<version>3.3.3</version>  
</dependency>  		
		

配置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"
	version="2.5">	
	
	<!-- ======================== 单点登录开始 ======================== -->  
    <!-- 用于单点退出,该过滤器用于实现单点登出功能,可选配置 -->  
    <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://localhost:8880/cas/login</param-value>  
            <!--这里的server是服务端的IP -->  
        </init-param>  
        <init-param>  
            <param-name>serverName</param-name>  
            <param-value>http://localhost:9002</param-value>
        </init-param>  
    </filter>  
    <filter-mapping>  
        <filter-name>CASFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  
  
    <!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->  
    <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:9000/cas</param-value>  
        </init-param>  
        <init-param>  
            <param-name>serverName</param-name>  
            <param-value>http://localhost:9002</param-value>
        </init-param>  
    </filter>  
    <filter-mapping>  
        <filter-name>CAS Validation Filter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  
  
    <!-- 该过滤器负责实现HttpServletRequest请求的包裹, 比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。 -->  
    <filter>  
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
        <filter-class>  
            org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  
  
    <!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。 比如AssertionHolder.getAssertion().getPrincipal().getName()。 -->  
    <filter>  
        <filter-name>CAS Assertion Thread Local Filter</filter-name>  
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>CAS Assertion Thread Local Filter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  
  
    <!-- ======================== 单点登录结束 ======================== -->  
</web-app>

这里主要用filter来实现单点登陆的拦截。其中filter-name为CASFilter用来做用户认证,这里配置cas服务端地址为http://localhost:8880/cas/login

<param-name>casServerLoginUrl</param-name>  
<param-value>http://localhost:8880/cas/login</param-value>

登陆系统时,casfilter会进行拦截,然后重定向到cas服务端,配置好服务端地址后还需要配置请求地址,即当前工程地址:

<init-param>  
      <param-name>serverName</param-name>  
      <param-value>http://localhost:9002</param-value>
</init-param>  

当系统进行用户认证时,向cas服务端发送请求时,需要携带请求工程的地址,因为认证完成后需要需要跳转回到请求的工程。

CAS Validation Filter为ticket验证器,org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter为ticket过滤器类,

它有两个重要参数,casServerUrlPrefix和serverName。casServerUrlPrefix也要配置为cas服务端地址,serverName配置为请求工程地址。

CASFilter和CAS Validation Filter是必须的,其他为可选

当配置了CAS HttpServletRequest Wrapper Filter过滤器,可以通过HttpServletRequest的getRemoteUser()方法获取单点登陆的用户名,虽然不配也能正常访问,但获取不到用户名信息,最好配上。CAS Assertion Thread Local Filter过滤器也是用来获取用户名的。

2)新建jsp写入如下代码:

helloWorld1!<%=request.getRemoteUser() %>

启动工程,新建一个同样的工程也启动,将cas服务端启动。浏览器输入http://localhost:9002结果可以看到跳转到了cas服务端登录界面。输入用户名密码登陆发现如下:

输入另外一个工程地址,发现不需要再登陆,显示和上面一样。这样就说明配置成功了。

浏览器输入http://localhost:8880/cas/logout为单点退出

刷新登陆的两个工程,发现跳转到cas服务端登陆地址了。这就是单点登出。如果单点登出后想要跳转到某个页面,需要修改cas服务端工程中WEB-INF路径下cas-servlet.xml配置文件。需要修改id为logoutAction的bean的属性p:followServiceRedirects="${cas.logout.followServiceRedirects:false}"为true,修改如下:

<bean id="logoutAction" class="org.jasig.cas.web.flow.LogoutAction"
        p:servicesManager-ref="servicesManager"
        p:followServiceRedirects="${cas.logout.followServiceRedirects:true}"/>

这样当登出的时候就会去重定向了。输入http://localhost:8880/cas/logout?service=xxxx就会重定向到xxx的地址

例如http://localhost:8880/cas/logout?service=http://localhost:8880/cas就是重定向到cas服务器登录页面。

http://localhost:8880/cas/logout?service=https://www.baidu.com/就是重定向到百度。

例如页面加入<a href="http://localhost:8880/cas/logout?service=http://localhost:8880/cas">退出登陆</a>标签

这样当我们点击退出登陆后,将会跳转到登录页面。

4.通过数据库获取用户信息

通过cas的WEB-INF路径下deployerConfigContext.xml可知,用户名信息是在id为proxyAuthenticationHandler的bean下,而这个bean是注入到id为authenticationManager的bean中的

在deployerConfigContext.xml中加入数据源配置

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
		p:driverClass="com.mysql.jdbc.Driver" 
		p:jdbcUrl="jdbc:mysql://127.0.0.1:3306/casdb?characterEncoding=utf8" 
		p:user="root" 
		p:password="123456" />
<bean id="passwordEncoder" 
		class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder" 
		c:encodingAlgorithm="MD5" 
		p:characterEncoding="UTF-8" />
<bean id="dbAuthHandler" 
		class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler" 
		p:dataSource-ref="dataSource" 
		p:sql="select password from tuser where username = ?" 
		p:passwordEncoder-ref="passwordEncoder"/>

其中dataSource为数据源配置,这里连接池为c3p0,可以看到dbAuthHandler引入了dataSource,要查询的表为tuser,要查询的字段为password,id为passwordEncoder的bean为密码加密适配器,如果密码没有加密,dbAuthHandler可以不配p:passwordEncoder-ref属性,由passwordEncoder的c:encodingAlgorithm可知加密算法为MD5。修改authenticationManager中<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />中key-ref为dbAuthHandler。

将c3p0,cas-server-support-jdbc,mysql-connector-java等jar包加入cas服务端工程WEB-INF中lib中(cas默认是没有这些jar包的),启动工程输入用户名密码一样可以成功。

5.修改自定义的登陆界面

 首先要更改登陆页面必须知道登陆页面的位置,而cas的登陆页面在工程路径下WEB-INF\view\jsp\default\ui的casLoginView.jsp。

所以当我们要使用自己的登陆页面时,必须在同目录下叫相同的名字。当然自定义页面是html,而改成jsp后是不能直接用的。

这里自定义页面如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>cas登录页面</title>
	</head>
	<body>
		<form>
			登录名:<input type="text" name="username" /><br />
			密码:<input type="password" name="password" />
		</form>
	</body>
</html>

打开原casLoginView.jsp文件发现有一行引入:<jsp:directive.include file="includes/top.jsp" />,找到对应的top.jsp:

将如上红色部分复制到自定义的登陆页面<html>标签上面部分,这样就将html页面变成了jsp页面:

<!DOCTYPE html>
<%@ page pageEncoding="UTF-8" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
	<head>
		<meta charset="utf-8">
		<title>cas登录页面</title>
	</head>
	<body>
		<form>
			登录名:<input type="text" name="username" /><br />
			密码:<input type="password" name="password" />
		</form>
	</body>
</html>

如果页面含有css,js可以将文件放入cas工程路径下js,css文件路径下

这样页面就可以正常访问了,但是想要成功登陆还需修改表单内容。

打开原登陆页面找到标签<form:form method="post" id="fm1" commandName="${commandName}" htmlEscape="true">,将自定义的登陆页面的form标签替换掉(如果原form标签有class属性等,将其放入替换后的标签),原</form>替换为</form:form>。form标签替换后还需要替换登录框(用户名和密码框)。找到用户名和密码的input框:

将其替换到自定义登录页面的input框,并去掉cssClass和cssErrorClass属性。加上自己的class属性。

最后还要替换登录按钮

找到如上代码,将已有的登录按钮替换(要加上三个隐藏域input框),同样的加上自己的class。

所有的替换后如下:

<!DOCTYPE html>
<%@ page pageEncoding="UTF-8" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
	<head>
		<meta charset="utf-8">
		<title>cas登录页面</title>
	</head>
	<body>
		<form:form method="post" id="fm1" commandName="${commandName}" htmlEscape="true">
			登录名:<form:input placeholder="请输入用户名"  id="username" size="25" tabindex="1" accesskey="${userNameAccessKey}" path="username" autocomplete="off" htmlEscape="true" /><br />
			密码:<form:password placeholder="请输入密码"  id="password" size="25" tabindex="2" path="password"  accesskey="${passwordAccessKey}" htmlEscape="true" autocomplete="off" /><br />
			<input type="hidden" name="lt" value="${loginTicket}" />
			<input type="hidden" name="execution" value="${flowExecutionKey}" />
			<input type="hidden" name="_eventId" value="submit" />

			<input class="btn-submit" name="submit" accesskey="l" value="登录" tabindex="4" type="submit" />
		</form:form>
	</body>
</html>

再次输入用户名密码就可以登录了。

猜你喜欢

转载自blog.csdn.net/u010689849/article/details/85221870
今日推荐