私のshiroの旅:16検証コード

7225 ワード

ブログを移動しましたhttp://blog.gogl.top
検証コードはほとんどのサイトで使われます.検証コードは一定のプログラムで悪意のある攻撃を効果的に処理できます.ここで検証コードを生成するツールを使うのはSimpleCaptchaです.現在公式サイトで最新版を見たのは1.2.1です.ダウンロードアドレス:http://sourceforge.net/projects/simplecaptcha/files/simplecaptcha-1.2.1.jar/download.認証コードを生成するツールクラスを以下に示します.
 
import java.awt.Color;
import java.awt.Font;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import nl.captcha.Captcha;
import nl.captcha.servlet.CaptchaServletUtil;
import nl.captcha.text.renderer.DefaultWordRenderer;
import nl.captcha.text.renderer.WordRenderer;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.concom.lang.exception.InvalidCaptchaException;
import com.google.common.collect.ImmutableList;

/**
 * @author Dylan
 * @mail [email protected]
 * @time 2014 4 9 
 */
public final class HttpCaptchaHelper {

	private final static Logger log = LoggerFactory.getLogger(HttpCaptchaHelper.class);

	private final static String CAPTCHA_PARAM = "captcha";
	
	private final static List FOUNTS = ImmutableList.of(
			  												  new Font("Courier New", Font.ITALIC, 40), 
			  												  new Font("Arial", Font.ITALIC, 40),
			  												  new Font("Times New Roman", Font.ITALIC, 40),
			  												  new Font("Verdana", Font.ITALIC, 40)
			 												 );

	private final static List COLORS = ImmutableList.of(Color.black);

	private final static WordRenderer RENDERER = new DefaultWordRenderer(COLORS, FOUNTS);
	
	private HttpCaptchaHelper() {}

	/**store captcha to session
	 * @param captcha
	 * @param session
	 */
	public static void storeCaptcha(Captcha captcha, HttpSession session) {

		DemonPredict.notNull(session, new InvalidCaptchaException("can not get session"));
		DemonPredict.notNull(captcha, new InvalidCaptchaException(String.format("no captcha in session 【%s】", session.getId())));
		
		synchronized (session) {
			if(log.isTraceEnabled()){
				log.trace(String.format("store captcha to session 【%s】", session.getId()));
			}
			session.setAttribute(CAPTCHA_PARAM, captcha);
		}
	}
	
	/**check captcha
	 * @param captchaCode
	 * @param session
	 */
	public static void checkCaptcha(String captchaCode,HttpSession session){
		
		if(StringUtils.isBlank(captchaCode)){
			throw new InvalidCaptchaException("captcha is blank");
		}
		
		DemonPredict.notNull(session, new InvalidCaptchaException("can not get session"));
		
		Captcha captcha = (Captcha)session.getAttribute(CAPTCHA_PARAM);
		
		DemonPredict.notNull(captcha, new InvalidCaptchaException(String.format("no captcha in session 【%s】", session.getId())));
		
		DemonPredict.isTrue(captcha.isCorrect(captchaCode), new InvalidCaptchaException(String.format("the captcha is %s ,but user input %s",captcha.getAnswer(),captchaCode)));
	
		synchronized (captcha) {
			if(log.isTraceEnabled()){
				log.trace("remove captcha from session");
			}
			session.removeAttribute(CAPTCHA_PARAM);
		}
		
	}
	
	/**
	 * @return
	 */
	public static Captcha createCaptcha(){
		Captcha captcha = new Captcha.Builder(120, 40).addText(RENDERER).addNoise().build();
		return captcha;
	}
	
	/**
	 * @param response
	 * @param session
	 */
	public static void writeAndStoreCaptcha(HttpServletResponse response, HttpSession session){
		Captcha captcha = createCaptcha();
		CaptchaServletUtil.writeImage(response, captcha.getImage());
		storeCaptcha(captcha,session);
	}
	
}
 
 
 
その中のDemonPrect類は自分で書いた断言類で、ここではコードを与えません.読者は一つまたは第三者のカバンで提供する断言類を書くことができます.このツール類は主にCaptchaを生成し、Captchaのイメージをクライアントに書き込み、sessionにキャッシュし、check後にCaptchaをsessionから削除します.次にもう一つのツール類を提供します.主にshiroプロジェクトに対して、HttpCaptchaHelperをベースにしてさらにパッケージ化します.
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.web.subject.WebSubject;

import nl.captcha.Captcha;

import com.concom.lang.helper.HttpCaptchaHelper;

/**
 * @author Dylan
 * @mail [email protected]
 * @time 2014 4 9 
 */
public final class ShiroCaptchaHelper {

	
	private ShiroCaptchaHelper(){}
	
	
	/**
	 * @param captcha
	 */
	public static void storeCaptcha(Captcha captcha){
		HttpCaptchaHelper.storeCaptcha(captcha, getHttpSession());
	}
	
	
	/**
	 * @param captchaCode
	 */
	public static void checkCaptcha(String captchaCode){
		HttpCaptchaHelper.checkCaptcha(captchaCode, getHttpSession());
	}
	
	/**
	 * @param response
	 */
	public static void writeAndStoreCaptcha(HttpServletResponse response){
		HttpCaptchaHelper.writeAndStoreCaptcha(response, getHttpSession());
	}
	
	/**
	 * @return
	 */
	private static HttpSession getHttpSession(){
		ServletRequest request = ((WebSubject)SecurityUtils.getSubject()).getServletRequest(); 
		HttpSession session = ((HttpServletRequest)request).getSession(false);
		return session;
	}
}
 
 
 
以下はテスト用のcontrollerコードです.
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.concom.security.infrastructure.helper.ShiroCaptchaHelper;

@Controller
public class TestController {
	

	@RequestMapping(value="/captcha.html",method=RequestMethod.GET)
	public void captcha(HttpServletRequest request,HttpServletResponse response){
		
		ShiroCaptchaHelper.writeAndStoreCaptcha(response);
	}
	
	@RequestMapping(value="/check.html",method=RequestMethod.POST)
	public void checkCaptcha(HttpServletRequest request,HttpServletResponse response){
		
		String captchaCode = WebUtils.getCleanParam(request, "captcha");
		
		ShiroCaptchaHelper.checkCaptcha(captchaCode);
	}


}
 
 
ページの検証コードを取得するhtmlは
 





<script type="text/javascript">
$(function(){
	
	$(".captcha").click(function(){
		var captchaUrl =  "${ctx}/captcha.html?"+Math.random().toString();
		$("#captcha-img").attr("src",captchaUrl);
		$("#captcha").focus();
	});
	
});
</script>


	<form action="${ctx}/check.html" method="post">
	    : <input id="captcha" name="captcha" type="text"/>
	 (   <a id="captcha1" class="captcha" href="javascript:void(0)">   </a>)
	<input value="  " type="submit"/>
	</form>

</code></pre> 
  <p><br/>             ,   js       Math.random().toString(),     ie             。  ,             。</p> 
  <p> </p> 
  <p> </p> 
  <p> </p> 
  <p> </p> 
  <p> </p> 
 </div> 
</div>
                            </div>
                        </div>