图形验证码如何解决集群中使用问题

刚才写了一篇文章关于图形验证码的,感觉没有考虑集群情况。其实集群无非加一个集群缓存 将session换成redis或者memcatch。

今天记录一下 使用 redis做集群图形验证码的相关方案。

基于文章:

http://www.cnblogs.com/owenma/p/7375540.html

添加redis:

在获取和存储的地方使用的是redis封装好的cacheManager。

@RequestMapping(value = "/getKaptchaImage", method = RequestMethod.GET)
    public
    ModelAndView getImage(HttpServletRequest request, HttpServletResponse response) throws Exception{
        HttpSession session = request.getSession();
        Cache<String, String> kaptcha = cacheManager.getCache("kaptcha");
        String code = kaptcha.get(Constants.KAPTCHA_SESSION_KEY);

        System.out.println("******************验证码是: " + code + "******************");
        Producer captchaProducer = (Producer)SpringContextUtils.getBean("captchaProducer");
        response.setDateHeader("Expires", 0);

        // Set standard HTTP/1.1 no-cache headers.
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");

        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");

        // Set standard HTTP/1.0 no-cache header.
        response.setHeader("Pragma", "no-cache");

        // return a jpeg
        response.setContentType("image/jpeg");

        // create the text for the image
        String capText = captchaProducer.createText();

        // store the text in the session
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        kaptcha.put(Constants.KAPTCHA_SESSION_KEY, capText);

        // create the image with the text
        BufferedImage bi = captchaProducer.createImage(capText);
        ServletOutputStream out = response.getOutputStream();

        // write the data out
        ImageIO.write(bi, "jpg", out);
        try {
            out.flush();
        } finally {
            out.close();
        }
        return null;
    }

    @RequestMapping(value = "/checkKaptchaImage", method = RequestMethod.POST)
    public
    @ResponseBody
    Map<String, String> checkKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception{
        Map<String, String> returnMap = new HashMap<>();
        Cache<String, String> kaptcha = cacheManager.getCache("kaptcha");
        //从session中取出servlet生成的验证码text值
        String kaptchaExpected = kaptcha.get(Constants.KAPTCHA_SESSION_KEY);
        //获取用户页面输入的验证码
        String kaptchaReceived = request.getParameter("kaptcha");
        //校验验证码是否正确
        returnMap.put("code", "100");
        if (kaptchaExpected == null){
            returnMap.put("status", "expire");
            return returnMap;
        }
        if (!kaptchaReceived.equalsIgnoreCase(kaptchaExpected)){
            returnMap.put("status", "false");
            return returnMap;
        }
        returnMap.put("status", "true");
        return returnMap;
    }

  

2. cacheManager代码

package com.nc.shiro.cache;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;

public class RedisCacheManager implements CacheManager {

	private static final Logger logger = LoggerFactory
			.getLogger(RedisCacheManager.class);

	@Autowired
	private JedisConnectionFactory connectionFactory;

	private static  RedisRealOPT redisRealOPT;

	// fast lookup by name map
	private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();

	/**
	 * The Redis key prefix for caches
	 */
	private String keyPrefix = "shiro_redis_cache:";

	/**
	 * Returns the Redis session keys
	 * prefix.
	 * @return The prefix
	 */
	public String getKeyPrefix() {
		return keyPrefix;
	}

	/**
	 * Sets the Redis sessions key
	 * prefix.
	 * @param keyPrefix The prefix
	 */
	public void setKeyPrefix(String keyPrefix) {
		this.keyPrefix = keyPrefix;
	}

	@Override
	public <K, V> Cache<K, V>  getCache(String name) throws CacheException {
		logger.debug("获取名称为: " + name + " 的RedisCache实例");

		Cache c = caches.get(name);

		if (c == null) {
			redisRealOPT = new RedisRealOPT();
			redisRealOPT.setJedis(connectionFactory.getShardInfo().createResource());
			redisRealOPT.setExpire(getTTL(name));
			keyPrefix = name + ":";
			// create a new cache instance
			c = new RedisCache<K, V>(redisRealOPT, keyPrefix);

			// add it to the cache collection
			caches.put(name, c);
		}
//		else {
//			((RedisCache) c).getCache().setJedis(connectionFactory.getShardInfo().createResource());
//		}

		return c;
	}

	public JedisConnectionFactory getConnectionFactory() {
		return connectionFactory;
	}

	public void setConnectionFactory(JedisConnectionFactory connectionFactory) {
		this.connectionFactory = connectionFactory;
	}

	private int getTTL(String name){
		//获得路径
		File classPath = new File(this.getClass().getResource("/").getPath());
		File properties = new File(classPath.getPath() + "/cacheManager.properties");
		Properties prop = new Properties();
		try {
			prop.load(new FileInputStream(properties));
			String propertyNames = prop.stringPropertyNames().toString();
			if (propertyNames.contains(name)){
				String value = prop.getProperty(name).trim();
				return Integer.parseInt(value);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return 0;
	}

}

如果觉得有疑问或者对你有帮助 欢迎评论。

作者:森林木马

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意

转载文章之后必须在 文章页面明显位置给出作者和原文连接否则保留追究法律责任的权利。

时间: 2024-10-10 15:23:15

图形验证码如何解决集群中使用问题的相关文章

基于Oracle数据库锁机制,解决集群中的并发访问问题

1.需求 应用场景是这样的: 使用Oracle数据保存待办任务,使用状态字段区分任务是否已经被执行.多个Worker线程同时执行任务,执行成功或失败后,修改状态字段的值. 假设数据库表结构如下所示. create table Task( id varchar2(32), name varchar2(32), flag varchar2(1), worker varchar2(32) ); flag 可取的值包括:0-待办,1-已办,-1-失败待重试. 需要避免的问题: 多个Worker同时工作时

LVS集群中的IP负载均衡技术

章文嵩 ([email protected]) 转自LVS官方参考资料 2002 年 4 月 本文在分析服务器集群实现虚拟网络服务的相关技术上,详细描述了LVS集群中实现的三种IP负载均衡技术(VS/NAT.VS/TUN和VS/DR)的工作原理,以及它们的优缺点. 1.前言在 前面文章中,讲述了可伸缩网络服务的几种结构,它们都需要一个前端的负载调度器(或者多个进行主从备份).我们先分析实现虚拟网络服务的主要技术,指出 IP负载均衡技术是在负载调度器的实现技术中效率最高的.在已有的IP负载均衡技术

在开启DRS的集群中修复VMware虚拟主机启动问题

通过iSCSI方式连接到ESXi主机上的外挂存储意外失联了一段时间,导致部分虚拟主机在集群中呈现出孤立的状态,单独登陆到每台ESXi上可以看到这些虚拟主机都变成了unknow状态.因为有过上一次(VMware-存储断网之后无法添加vmx到清单)的经验,所有操作等待存储恢复与ESXi连接之后再进行操作,这样可以尽量避免虚拟主机意外“消失”. 前奏 最终,存储网络恢复正常,期间经历了大约1个小时,有绝大多数的Windows虚拟主机在存储网络恢复正常之后继续正常工作:有少部分的Linux虚拟主机内部E

Hadoop学习笔记—13.分布式集群中的动态添加与下架

开篇:在本笔记系列的第一篇中,我们介绍了如何搭建伪分布与分布模式的Hadoop集群.现在,我们来了解一下在一个Hadoop分布式集群中,如何动态(不关机且正在运行的情况下)地添加一个Hadoop节点与下架一个Hadoop节点. 一.实验环境结构 本次试验,我们构建的集群是一个主节点,三个从节点的结构,其中三个从节点的性能配置各不相同,这里我们主要在虚拟机中的内存设置这三个从节点分别为:512MB.512MB与256MB.首先,我们暂时只设置两个从节点,另外一个作为动态添加节点的时候使用.主节点与

关于 tomcat 集群中 session 共享的三种方法

前两种均需要使用 memcached 或 redis 存储 session ,最后一种使用 terracotta 服务器共享. 建议使用 redis ,不仅仅因为它可以将缓存的内容持久化,还因为它支持的单个对象比较大,而且数据类型丰富, 不只是缓存 session ,还可以做其他用途,一举几得啊. 1.使用 filter 方法存储 这种方法比较推荐,因为它的服务器使用范围比较多,不仅限于 tomcat ,而且实现的原理比较简单容易控制. 可以使用 memcached-session-filter

如何在tomcat集群中实现Session共享

转自:http://www.toutiao.com/i6388049068718817794/ Apache集群实现Tomcat的Session共享配置其实很简单,在Tomcat自带的文档中有详细的说明( /docs/cluster-howto.html ),只不过是英语的,所以联合 下面根据说下怎么配置吧: 1.既然是集群肯定要多准备几个Tomcat来模拟,比如分别为Tomcat01.Tomcat02.Tomcat03. 如果各Tomcat程序放在不同的机器上,那么就不会有端口的冲突.如果是放

Oracle 学习之RAC(八) 向集群中添加节点

我们前面安装了两个节点的RAC. 我们现在将第三个节点11grac3,添加到我们集群中.第三个节点一定要按照集群环境准备一文描述,准备环境.请参考 http://lqding.blog.51cto.com/9123978/1684159 安装前检查 11grac1-> pwd /u01/app/11.2.0/grid/bin 11grac1-> ./cluvfy stage -pre nodeadd -n 11grac3 -fixup -verbose 检查结果 Performing pre-

MSM实现tomcat集群中session共享的高可用

目录 1.测试环境概述 2.MSM简介 2.1.MSM的特性 2.2.MSM要解决的问题 2.3.MSM的工作原理 3.环境搭建 3.1.memcached安装 3.2.jkd与tomcat安装配置 3.3.MSM sticky session + kryo模式的配置 3.4.MSM no-sticky session + kryo模式的配置 4.思考与总结 1.测试环境概述 采用两台linux x64主机,主机上分别安装memcached与tomcat,memcached提供key/value

负载均衡集群中的session解决方案

前言 在我们给Web站点使用负载均衡之后,必须面临的一个重要问题就是Session的处理办法,无论是PHP.Python.Ruby还是Java,只要使用服务器保存Session,在做负载均衡时都需要考虑Session的问题. 分享目录: 问题在哪里?如何处理? 会话保持(案例:Nginx.Haproxy) 会话复制(案例:Tomcat) 会话共享(案例:Memcached.Redis) 问题在哪里? 从用户端来解释,就是当一个用户第一次访问被负载均衡代理到后端服务器A并登录后,服务器A上保留了用