前言
2.5.1、版本信息
CAS服務器版本爲4.0.0Redis數據庫版本爲4.0.6
2.5.2、Redis相關的配置
Redis是一個開源的使用ANSI C語言編寫、遵守BSD協議、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。它通常被稱爲數據結構服務器,因爲值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等類型。本文是基於Java語言的開發,使用Java語言調用Redis的相關服務,需要調用相關jar包——jedis-2.9.0.jar。將該jar包複製到cas服務器工程中,路徑 cas/WEB-INF/lib 下。
Redis數據庫的安裝略,請自行百度安裝。
建議安裝一個Redis客戶端——RedisDesktopManager,用來查看數據庫信息。
2.5.3、CAS服務器的改造
2.5.3.1、自定義CAS鏈接Redis類
在myeclipse中創建Java web工程,工程名隨意。將Redis的連接包jedis-2.9.0.jar 和CAS服務的cas-server-core-4.0.0.jar導入到工程中,cas-server-core-4.0.0.jar在你下載的cas-server-4.0.0-release的 .../cas-server-4.0.0/modules下。在工程中創建名爲 org.jasig.cas.ticket 的包,在該包下創建名爲RedisTicketRegistry的類,在該類中定義CAS與Redis交互的方法。該類需要繼承CAS自身的抽象類——AbstractDistributedTicketRegistry。代碼如下:
package org.jasig.cas.ticket;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import org.jasig.cas.ticket.Ticket;
import org.jasig.cas.ticket.TicketGrantingTicket;
import org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* 使用Redis存儲Ticket
* @author xyong
*/
public class RedisTicketRegistry extends AbstractDistributedTicketRegistry
{
private static int redisDatabaseNum;
private static String hosts;
private static int port;
private static int connTimeout;
//private static String redisPassword;
/**
* ST最大空閒時間
*/
private static int st_time;
/**
* TGT最大空閒時間
*/
private static int tgt_time;
private static JedisPool cachePool;
static
{
//redisDatabaseNum = SysPropertiesUtil.getPropertyInt("redis_database_num");
redisDatabaseNum = 7; //選擇存儲的redis數據庫,redis默認有15個數據庫。我的幸運數字是7,所以我選用第七個數據庫。
//hosts = SysPropertiesUtil.getProperty("redis_hosts");
hosts = "10.4.123.100";
//port = SysPropertiesUtil.getPropertyInt("redis_port");
port = 6379;
//connTimeout = SysPropertiesUtil.getPropertyInt("redis_conn_timeout");
//redisPassword = SysPropertiesUtil.getProperty("redis_password");
//st_time = SysPropertiesUtil.getPropertyInt("st_time");
st_time = 10000; //10秒
//tgt_time = SysPropertiesUtil.getPropertyInt("tgt_time");
tgt_time = 7200000; //7200秒,2個小時
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(1000);
//config.setTestOnBorrow(true);
cachePool = new JedisPool(config, hosts, port);
}
@Override
public void addTicket(Ticket ticket)
{
Jedis jedis = cachePool.getResource();
jedis.select(redisDatabaseNum);
int seconds = 0;
String key = ticket.getId();
if (ticket instanceof TicketGrantingTicket)
{
seconds = tgt_time / 1000;
}
else
{
seconds = st_time / 1000;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try
{
oos = new ObjectOutputStream(bos);
oos.writeObject(ticket);
}
catch (Exception e)
{
logger.error("adding ticket to redis error.");
}
finally
{
try
{
if (null != oos)
oos.close();
}
catch (Exception e)
{
logger.error("oos closing error when adding ticket to redis.");
}
}
jedis.set(key.getBytes(), bos.toByteArray());
jedis.expire(key.getBytes(), seconds); //設置redis失效時間
jedis.close();
}
@Override
public boolean deleteTicket(String ticketId)
{
if (ticketId == null)
{
return false;
}
Jedis jedis = cachePool.getResource();
jedis.select(redisDatabaseNum);
jedis.del(ticketId.getBytes());
jedis.close();
return true;
}
@Override
public Ticket getTicket(String ticketId)
{
return getProxiedTicketInstance(getRawTicket(ticketId));
}
private Ticket getRawTicket(final String ticketId)
{
if (null == ticketId)
{
return null;
}
Jedis jedis = cachePool.getResource();
jedis.select(redisDatabaseNum);
Ticket ticket = null;
byte[] bytes = jedis.get(ticketId.getBytes());
if (bytes == null || bytes.length < 1)
{
return null;
}
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = null;
try
{
ois = new ObjectInputStream(bais);
ticket = (Ticket) ois.readObject();
}
catch (Exception e)
{
e.printStackTrace();
logger.error("getting ticket to redis error.");
}
finally
{
try
{
if (null != ois)
{
ois.close();
}
}
catch (Exception e)
{
e.printStackTrace();
logger.error("ois closing error when getting ticket to redis.");
}
}
jedis.close();
return ticket;
}
@Override
public Collection<Ticket> getTickets()
{
throw new UnsupportedOperationException("GetTickets not supported.");
}
@Override
protected boolean needsCallback()
{
return false;
}
@Override
protected void updateTicket(Ticket ticket)
{
this.addTicket(ticket);
}
}
找到myeclipse workspace中RedisTicketRegistry.class文件,該文件在workspace\CASTransform\WebRoot\WEB-INF\classes\org\jasig\cas\ticket目錄下。右鍵打開cas-server-core-4.0.0.jar壓縮包(不要解壓),再按照\org\jasig\cas\ticket\路徑打開文件夾,將RedisTicketRegistry.class拖到該文件夾下,結果如圖2.5.3.1所示。
2.5.3.2、修改ticketRegistry.xml
在CAS的cas/WEB-INF/spring-configuration下獲取ticketRegistry.xml。打開ticketRegistry.xml,修改id爲ticketRegistry的bean的路徑,並註釋掉ticketRegistry.xml下方的配置信息,修改後的ticketRegistry.xml內容如下所示:<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to Jasig under one or more contributor license
agreements. See the NOTICE file distributed with this work
for additional information regarding copyright ownership.
Jasig licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a
copy of the License at the following location:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<description>
Configuration for the default TicketRegistry which stores the tickets in-memory and cleans them out as specified intervals.
</description>
<!-- Ticket Registry -->
<!-- <bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.DefaultTicketRegistry" /> -->
<bean id="ticketRegistry" class="org.jasig.cas.ticket.RedisTicketRegistry" />
<!--Quartz -->
<!-- TICKET REGISTRY CLEANER -->
<!-- <bean id="ticketRegistryCleaner" class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner"
p:ticketRegistry-ref="ticketRegistry"
p:logoutManager-ref="logoutManager" />
<bean id="jobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
p:targetObject-ref="ticketRegistryCleaner"
p:targetMethod="clean" />
<bean id="triggerJobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.SimpleTriggerBean"
p:jobDetail-ref="jobDetailTicketRegistryCleaner"
p:startDelay="20000"
p:repeatInterval="5000000" /> -->
</beans>
備註:你可以直接用上面的配置信息覆蓋掉你原來的ticketRegistry.xml配置信息。用修改後的ticketRegistry.xml覆蓋掉CAS服務器中原來的ticketRegistry.xml