中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringMVC中使用Kaptcha驗證碼組件生成比較安全的驗證碼

發布時間:2020-07-04 22:48:18 來源:網絡 閱讀:3068 作者:pangfc 欄目:開發技術

一 簡介

Kaptcha是一個基于SimpleCaptcha的驗證碼開源項目,在我們的項目中使用Kaptcha組件可以快速生成比較安全的驗證碼。同時Kaptcha還提供了許多的參數可以讓我們自定義生成的驗證碼樣式

jar包的官網下載地址:https://code.google.com/archive/p/kaptcha/downloads

當然,為了照顧一些翻不了墻的同學,我也在51cto上上傳了一份Kaptcha最新的的jar包(kaptcha-2.3.2),傳送門:http://down.51cto.com/data/2257293

二 代碼實現

(1)在項目中添加Kaptcha相關jar包:

具體就是:

  • kaptcha-2.3.2.jar

(2)在spring的配置文件中添加Kaptcha相關的配置:

	<!-- Kaptcha驗證碼生成器 -->
	<bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">
		<property name="config">
			<bean class="com.google.code.kaptcha.util.Config">
				<constructor-arg>
					<props>
						<prop key="kaptcha.border">no</prop><!-- 是否有邊框 -->
						<prop key="kaptcha.noise.color">25,25,25</prop><!-- 干擾線顏色 -->
						<prop key="kaptcha.obscurificator.impl">com.google.code.kaptcha.impl.ShadowGimpy</prop>
						<prop key="kaptcha.p_w_picpath.width">140</prop>
						<prop key="kaptcha.p_w_picpath.height">40</prop>
						<prop key="kaptcha.textproducer.char.string">AZWSXEDCRFVTGBYHNUJMIKLP23456789</prop>
						<prop key="kaptcha.textproducer.font.color">4,14,156</prop><!-- 驗證碼字體顏色 -->
						<prop key="kaptcha.textproducer.font.size">36</prop><!-- 驗證碼字體大小 -->
						<prop key="kaptcha.session.key">code</prop>
						<prop key="kaptcha.textproducer.char.length">5</prop><!-- 驗證碼個數 -->
						<prop key="kaptcha.textproducer.font.names">宋體,楷體,微軟雅黑</prop>
					</props>
				</constructor-arg>
			</bean>
		</property>
	</bean>

注:其他的一些可選配置:

kaptcha.border  是否有邊框  默認為true  我們可以自己設置yes,no
kaptcha.border.color   邊框顏色   默認為Color.BLACK
kaptcha.border.thickness  邊框粗細度  默認為1
kaptcha.producer.impl   驗證碼生成器  默認為DefaultKaptcha
kaptcha.textproducer.impl   驗證碼文本生成器  默認為DefaultTextCreator
kaptcha.textproducer.char.string   驗證碼文本字符內容范圍  默認為abcde2345678gfynmnpwx
kaptcha.textproducer.char.length   驗證碼文本字符長度  默認為5
kaptcha.textproducer.font.names    驗證碼文本字體樣式  默認為new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
kaptcha.textproducer.font.size   驗證碼文本字符大小  默認為40
kaptcha.textproducer.font.color  驗證碼文本字符顏色  默認為Color.BLACK
kaptcha.textproducer.char.space  驗證碼文本字符間距  默認為2
kaptcha.noise.impl    驗證碼噪點生成對象  默認為DefaultNoise
kaptcha.noise.color   驗證碼噪點顏色   默認為Color.BLACK
kaptcha.obscurificator.impl   驗證碼樣式引擎  默認為WaterRipple
kaptcha.word.impl   驗證碼文本字符渲染   默認為DefaultWordRenderer
kaptcha.background.impl   驗證碼背景生成器   默認為DefaultBackground
kaptcha.background.clear.from   驗證碼背景顏色漸進   默認為Color.LIGHT_GRAY
kaptcha.background.clear.to   驗證碼背景顏色漸進   默認為Color.WHITE
kaptcha.p_w_picpath.width   驗證碼圖片寬度  默認為200
kaptcha.p_w_picpath.height  驗證碼圖片高度  默認為50

(3)在Controller中分別添加用于生成驗證碼以及校驗驗證碼的controller:

package cn.zifangsky.controller;

import java.awt.p_w_picpath.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.p_w_picpathio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;

import cn.zifangsky.model.VerifyCode;

@Controller
public class CaptchaController {
	
	@Autowired
	private Producer producer;
	
	/**
	 * 生成驗證碼
	 * @param request
	 * @param response
	 */
	@RequestMapping("/user/user/verify.html")
	public void generate(HttpServletRequest request,HttpServletResponse response){
		response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("p_w_picpath/jpeg");
        
        String validateText = producer.createText();  //生成驗證碼文字
        //存儲到session中
        request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, validateText);
        
        BufferedImage bImage = producer.createImage(validateText);
        try {
			ServletOutputStream outputStream = response.getOutputStream();
			ImageIO.write(bImage, "jpg", outputStream);
			outputStream.flush();
			
			outputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 校驗驗證碼
	 * @return 返回是否校驗成功
	 */
	@RequestMapping(value="/user/user/checkVerifyCode.json",method={RequestMethod.POST})
	@ResponseBody
	public Map<String, String> check(@RequestBody VerifyCode verifyCode,HttpServletRequest request){
		HttpSession session = request.getSession();
		Map<String, String> result = new HashMap<>();
		
		//session中的驗證碼
		String codeFromSession = (String) session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
		session.removeAttribute(Constants.KAPTCHA_SESSION_KEY);  //使用之后刪除
		
		if(StringUtils.isNotBlank(verifyCode.getVerifyCodeValue()) && StringUtils.isNotBlank(codeFromSession)){
			if(verifyCode.getVerifyCodeValue().equalsIgnoreCase(codeFromSession)){
				session.setAttribute("codeCheck", true);  //設置校驗成功標志
				result.put("result", "ok");
			}else{
				result.put("result", "error");
			}
		}else{
			result.put("result", "error");
		}
		return result;
	}
}

注:這里使用json請求異步校驗驗證時使用了Jackson來將前臺傳遞過來的json字符串自動轉換成Java對象,因此如果像我這里采用異步校驗的話還需要配置Jackson相關的配置,具體配置如下:

i)VerifyCode.java

package cn.zifangsky.model;

public class VerifyCode {
	private String verifyCodeValue;

	public String getVerifyCodeValue() {
		return verifyCodeValue;
	}

	public void setVerifyCodeValue(String verifyCodeValue) {
		this.verifyCodeValue = verifyCodeValue;
	}
	
}

ii)向項目中引入Jackson相關的jar包:

下載地址如下:http://down.51cto.com/data/2257291

iii)在SpringMVC的配置文件中添加以下配置:

	<bean id="mappingJacksonHttpMessageConverter"
        class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
        <property name="objectMapper">
            <bean class="org.codehaus.jackson.map.ObjectMapper">
                <property name="dateFormat">
                    <bean class="java.text.SimpleDateFormat">
                        <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"></constructor-arg>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
    <!-- 啟動Spring MVC的注解功能,完成請求和注解POJO的映射 -->
    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="mappingJacksonHttpMessageConverter" /><!-- json轉換器 -->
            </list>
        </property>
    </bean>
    <mvc:annotation-driven
        content-negotiation-manager="contentNegotiationManager" />
    <bean id="contentNegotiationManager"
        class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <!-- true,開啟擴展名支持,false關閉支持 -->
        <property name="favorPathExtension" value="false" />
        <!-- 用于開啟 /userinfo/123?format=json的支持 -->
        <property name="favorParameter" value="true" />
        <!-- 設置為true以忽略對Accept Header的支持 -->
        <property name="ignoreAcceptHeader" value="false" />
        <property name="mediaTypes">
            <value>
                atom=application/atom+xml
                html=text/html
                json=application/json
                xml=application/xml
                *=*/*
            </value>
        </property>
    </bean>

(4)登錄頁面:

<%@page import="java.security.SecureRandom"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<c:set var="path" value="${pageContext.request.contextPath}" />
<title>ShiroDemo2</title>
<script src="${path}/scripts/jquery/jquery-1.9.0.min.js"
	type="text/javascript"></script>
<script type="text/javascript">
	$(function() {
		$("#verifyImg").click(
				function() {
					$("#message").text("");
					$(this).attr(
							"src",
							"<c:url value='/user/user/verify.html'/>?"
									+ Math.floor(Math.random() * 100));
				});
		$("#verifyCode").keyup(function() {
			var verifyCodeValue = $("#verifyCode").val().replace("/\s/g", "");
			var data = {"verifyCodeValue":verifyCodeValue};
			if (verifyCodeValue.length == 5) {
				$.ajax({
					url : "<c:url value='/user/user/checkVerifyCode.json'/>",
					type : "POST",
					contentType : 'application/json; charset=utf-8',
					data : JSON.stringify(data),
					success : function(response) {
						if (response.result == "ok") {
							$("#message").text("ok");
							$("#password").focus();
						} else if(response.result == "error"){
							$("#message").text("error");
							$("#verifyImg").attr("src","<c:url value='/user/user/verify.html'/>?"
											+ Math.floor(Math.random() * 100));
						}
					},
					error : function(response){
						alert("提交失敗,請重新提交");
					}
				});
			}
		});
		$("#submit").click(function(){
			var action = "<c:url value='/user/user/check.json'/>";
			var data = {"username":$("#username").val(),"password":$("#password").val()};
			$.ajax({
				url : action,
				type:"POST",
				contentType:'application/json',
				data:JSON.stringify(data),
				success:function(response){
					if(response.result == "success"){
						window.location.href ="<c:url value='/user/index.html'/>";
					}else if(response.result == "error"){
						$("#error").text("登錄失敗,請重新提交");
						$("#verifyImg").attr("src","<c:url value='/user/user/verify.html'/>?"
								+ Math.floor(Math.random() * 100));
					}
				},
				error:function(response){
					alert("提交失敗,請重新提交");
				}
			});
		});
		
	});
</script>
<STYLE type="text/css">
#login {
	width: 400px;
	height: 280px;
	position: absolute;
	left: 50%;
	top: 50%;
	margin-left: -200px;
	margin-top: -140px;
	border: 1px;
	align: center;
}

#form {
	width: 300px;
	height: 160px;
	position: relative;
	left: 50%;
	top: 50%;
	margin-left: -150px;
	margin-top: -80px;
	text-align: center";
}
</STYLE>
</head>
<body>
	<div id="login">
		<div id="form">
			<form id="myform">
				<div>
					<input type="text" id="username" name="username" placeholder="用戶名" />
					<input type="password" id="password" name="password"
						placeholder="密碼" />
				</div>
				<div>
					<input type="text" id="verifyCode" name="verifyCode" maxlength="5"
						placeholder="驗證碼" /> <img id="verifyImg" name="verifyImg"
						title="點擊刷新" src="<c:url value='/user/user/verify.html'/>"
						><span id="message"
						></span>
				</div>
				<div id="submit">
					<input type="submit" value="登錄" />
					<div id="error" ></div>
				</div>
			</form>
		</div>
	</div>
</body>
</html>

前臺登錄頁面這里就不做過多解釋了,都是jQuery的一些寫法。代碼不難,如果了解jQuery的一些基本用法的話,理解上面的代碼應該挺容易的。當然,最后進行登錄校驗時需要判斷session中是否有“codeCheck”這個參數,用于判斷驗證碼是否已經校驗成功過。具體的代碼如下:

	/**
	 * 登錄校驗
	 * 
	 * @param UsrUser
	 *            登錄時的User對象,包括form表單中的用戶名和密碼
	 * @param request
	 * @return 是否登錄成功標志
	 */
	@RequestMapping(value = "/user/user/check.json",method={RequestMethod.POST})
	@ResponseBody
	public Map<String, String> loginCheck(@RequestBody UsrUser user,HttpServletRequest request) {
		HttpSession session = request.getSession();
		Map<String, String> result = new HashMap<>();

		Boolean codeCheck = (Boolean) session.getAttribute("codeCheck");  //驗證碼是否校驗成功標志
		session.removeAttribute("codeCheck");
		
		if (codeCheck != null && codeCheck) {
			UsrUserBO userBO = userManager.login(user.getUsername(), user.getPassword());
			if (userBO != null) {
				session.setAttribute("userBO", userBO); // 登錄成功之后加入session中
				result.put("result", "success");
			} else {
				result.put("result", "error");
			}
		}else{
			result.put("result", "error");
		}
		return result;
	}

(5)最后生成的驗證碼效果如下:

SpringMVC中使用Kaptcha驗證碼組件生成比較安全的驗證碼

SpringMVC中使用Kaptcha驗證碼組件生成比較安全的驗證碼

參考文章:

  • https://my.oschina.net/u/1450300/blog/486377

PS:上面圖片中的水印是我個人博客的域名,因此還請管理員手下留情不要給我標為“轉載文章”,謝謝!!!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平遥县| 页游| 电白县| 红原县| 阳山县| 新龙县| 济南市| 潞城市| 弋阳县| 南涧| 珠海市| 交口县| 南宁市| 措美县| 无锡市| 奉新县| 汕尾市| 两当县| 互助| 克拉玛依市| 白河县| 余干县| 璧山县| 达日县| 措勤县| 广水市| 政和县| 武强县| 昌吉市| 十堰市| 望江县| 塔城市| 东源县| 石家庄市| 苍溪县| 仙居县| 华亭县| 红安县| 高雄市| 云梦县| 从江县|