圖形驗證碼如何解決集群中使用問題


       剛才寫了一篇文章關於圖形驗證碼的,感覺沒有考慮集群情況。其實集群無非加一個集群緩存 將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;
	}


}

 

如果覺得有疑問或者對你有幫助 歡迎評論。

作者:森林木馬

  如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!歡迎各位轉載,但是未經作者本人同意 

轉載文章之后必須在 文章頁面明顯位置給出作者和原文連接否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM