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

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

今天记录一下 使用 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;
	}


}

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

作者:森林木马

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

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

原文地址:https://www.cnblogs.com/owenma/p/7375652.html