前言:
驗(yàn)證碼在項(xiàng)目肯定會(huì)用得到木人,本案例是在window上運(yùn)行的,若kaptcha驗(yàn)證碼在Linux上顯示的是一堆亂碼嗓袱,可能是因?yàn)長(zhǎng)inux沒(méi)有中文字體庫(kù)和中文字體造成的奸披,可進(jìn)行如下操作:
歡迎大家關(guān)注我的公眾號(hào) javawebkf,目前正在慢慢地將簡(jiǎn)書(shū)文章搬到公眾號(hào)蝎土,以后簡(jiǎn)書(shū)和公眾號(hào)文章將同步更新视哑,且簡(jiǎn)書(shū)上的付費(fèi)文章在公眾號(hào)上將免費(fèi)。
1誊涯、判斷有沒(méi)有中文字體庫(kù):
fc-list
2挡毅、若沒(méi)有就安裝:
yum -y install fontconfig
安裝成功后可以在/usr/share
目錄下看到fonts
和fontconfig
目錄,之前是沒(méi)有的暴构。接著在fonts
目錄下新建chinese
目錄跪呈。然后打開(kāi)我們windows電腦C盤的windows/fonts
目錄段磨,找到你需要安裝的字體,上傳到Linux的剛才新建的chinese目錄下耗绿。
3苹支、修改chinese目錄的權(quán)限:
chmod -R 755 /usr/share/fonts/chinese
4、接下來(lái)安裝ttmkfdir:
yum -y install ttmkfdir
5误阻、然后執(zhí)行ttmkfdir命令:
ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
6债蜜、然后修改字體配置文件,新增內(nèi)容如下圖:
vim /etc/fonts/fonts.conf
7究反、最后重啟Linux服務(wù)器(網(wǎng)上說(shuō)執(zhí)行fc-cache就可以不用重啟寻定,你們可以自行測(cè)試,我測(cè)試是沒(méi)用的)精耐。
一狼速、kaptcha簡(jiǎn)介:
kaptcha 是一個(gè)很有用的驗(yàn)證碼生成工具,由于它有許多可配置項(xiàng)卦停,所以用它可以簡(jiǎn)單快捷的生成各式各樣的驗(yàn)證碼向胡。點(diǎn)我下載源碼。
二沫浆、開(kāi)發(fā)工具及使用的核心技術(shù):
1、eclipse
2淮捆、mybatis
3、spring
4承边、springmvc
5、kaptcha
本文將介紹kaptcha兩種使用方式:
方式一:在spring-kaptcha.xml中配置
方式二:在web.xml中配置
三蚁飒、正式開(kāi)始:
一、搭骨架
1翅溺、添加依賴:
<!-- 驗(yàn)證碼 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
要使用kaptcha驗(yàn)證碼伊滋,除了spring和mybatis那些依賴笑旺,只需引入這一個(gè)即可昼浦。
2、完善配置文件
①spring-dao.xml
<!-- 配置整合mybatis過(guò)程 -->
<!-- 1筒主、配置數(shù)據(jù)庫(kù)相關(guān)參數(shù)properties的屬性:${url} -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 2关噪、配置數(shù)據(jù)庫(kù)連接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置連接池屬性 -->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- c3p0連接池的私有屬性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 關(guān)閉連接不自動(dòng)commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 獲取連接超時(shí)時(shí)間 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 當(dāng)獲取連接失敗時(shí)重試次數(shù) -->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- 3、配置mybatis的sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自動(dòng)掃描mappers.xml文件 -->
<property name="mapperLocations" value="classpath:mappers/*.xml"/>
<!-- mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 掃描entity包乌妙,使用別名 -->
<property name="typeAliasesPackage" value="com.zhu.kaptcha.entity"></property>
</bean>
<!-- 4使兔、DAO接口所在包名,Spring會(huì)自動(dòng)查找其下的類 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zhu.kaptcha.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
②spring-service.xml
<!-- 掃描service包下所有使用注解的類型 -->
<context:component-scan base-package="com.zhu.kaptcha.service"/>
<!-- 事務(wù)管理 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置基于注解的聲明式事物 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
③spring-web.xml
<!-- 配置springmvc -->
<!-- 1冠胯、開(kāi)啟springMvc注解模式 -->
<mvc:annotation-driven />
<!--2火诸、定義視圖解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 3、掃描web相關(guān)的bean -->
<context:component-scan base-package="com.zhu.kaptcha.controller"/>
④web.xml
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 編碼過(guò)濾器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
至此荠察,骨架就搭起來(lái)了置蜀,接下來(lái)完成對(duì)數(shù)據(jù)庫(kù)的操作奈搜。
二、對(duì)數(shù)據(jù)庫(kù)的操作
1盯荤、entity層
User.java
public class User {
private int uid;
private String userName;
private String passWord;
}
2馋吗、dao層
UserDao.java
public interface UserDao {
User findUserByUserName(String userName);
}
UserDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhu.kaptcha.dao.UserDao">
<select id="findUserByUserName" resultType="com.zhu.kaptcha.entity.User">
SELECT *
FROM tb_user
WHERE
user_name=#{userName}
</select>
</mapper>
3、service層
UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public boolean login(String userName, String passWord) {
User user = userDao.findUserByUserName(userName);
if (passWord.equals(user.getPassWord())) {
return true;
} else {
return false;
}
}
}
注:寫(xiě)到dao層和service層應(yīng)該做一下Junit測(cè)試秋秤,測(cè)試比較簡(jiǎn)單宏粤,這里就不做說(shuō)明了。
三灼卢、整合kaptcha
方式一绍哎、通過(guò)spring-kaptcha.xml配置:
1、在resources的spring文件夾下新建spring-kaptcha.xml配置文件鞋真,內(nèi)容如下:
spring-kaptcha.xml
<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">yes</prop>
<prop key="kaptcha.border.color">105,179,90</prop>
<prop key="kaptcha.textproducer.font.color">blue</prop>
<prop key="kaptcha.image.width">125</prop>
<prop key="kaptcha.image.height">45</prop>
<prop key="kaptcha.textproducer.font.size">45</prop>
<prop key="kaptcha.session.key">code</prop>
<prop key="kaptcha.textproducer.char.length">4</prop>
<prop key="kaptcha.textproducer.font.names">宋體,楷體,微軟雅黑</prop>
</props>
</constructor-arg>
</bean>
</property>
</bean>
注:這個(gè)bean就是配置了一些驗(yàn)證碼的屬性崇堰,也可以直接寫(xiě)在spring-web.xml中,根據(jù)個(gè)人習(xí)慣涩咖,我喜歡把不同模塊的配置寫(xiě)在不同的文件中海诲。
2、新建一個(gè)controller用于生成驗(yàn)證碼
CodeController.java
@Controller
public class CodeController {
@Autowired
private Producer captchaProducer = null;
@RequestMapping("/kaptcha")
public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
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("image/jpeg");
//生成驗(yàn)證碼
String capText = captchaProducer.createText();
session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
//向客戶端寫(xiě)出
BufferedImage bi = captchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
}
注意:這個(gè)controller的路由為“kaptcha”檩互,那么等下前端驗(yàn)證碼的src就為kaptcha.jpg 特幔。
3、新建一個(gè)工具類用于比對(duì)驗(yàn)證碼
CodeUtil.java
public class CodeUtil {
/**
* 將獲取到的前端參數(shù)轉(zhuǎn)為string類型
* @param request
* @param key
* @return
*/
public static String getString(HttpServletRequest request,String key) {
try {
String result = request.getParameter(key);
if(result != null) {
result = result.trim();
}
if("".equals(result)) {
result = null;
}
return result;
}catch(Exception e) {
return null;
}
}
/**
* 驗(yàn)證碼校驗(yàn)
* @param request
* @return
*/
public static boolean checkVerifyCode(HttpServletRequest request) {
//獲取生成的驗(yàn)證碼
String verifyCodeExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
//獲取用戶輸入的驗(yàn)證碼
String verifyCodeActual = CodeUtil.getString(request, "verifyCodeActual");
if(verifyCodeActual == null ||!verifyCodeActual.equals(verifyCodeExpected)) {
return false;
}
return true;
}
}
注意:這里get傳的參數(shù)名為“verifyCodeActual”闸昨,那么等下在頁(yè)面中驗(yàn)證碼的name值也得為這個(gè)蚯斯。
接下來(lái)就可以使用驗(yàn)證碼了!
4零院、用戶登錄的Controller
UserController.java
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public String login(@RequestParam("userName") String userName, @RequestParam("passWord") String passWord,
HttpServletRequest request) {
boolean result = userService.login(userName, passWord);
if (!CodeUtil.checkVerifyCode(request)) {
request.setAttribute("codeErr", "驗(yàn)證碼有誤!");
return "fail";
} else {
if (result) {
request.setAttribute("user", userName);
return "success";
} else {
request.setAttribute("errMsg", "用戶名或密碼錯(cuò)誤!");
return "fail";
}
}
}
}
注:這里調(diào)用CodeUtil工具類比對(duì)輸入的驗(yàn)證碼是否正確溉跃。
5、前端頁(yè)面
login.jsp
<%@ page language="java" import="java.util.*"
contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>登錄</title>
<script type="text/javascript">
function refresh() {
document.getElementById('captcha_img').src="kaptcha.jpg?"+Math.random();
}
</script>
</head>
<body>
<form action="${pageContext.request.contextPath }/user/login" method="post">
userName:<input type="text" name="userName" /><br />
password:<input type="password" name="passWord" /><br />
驗(yàn)證碼: <input type="text" placeholder="請(qǐng)輸入驗(yàn)證碼" name="verifyCodeActual">
<div class="item-input">
<img id="captcha_img" alt="點(diǎn)擊更換" title="點(diǎn)擊更換"
onclick="refresh()" src="kaptcha.jpg" />
</div>
<input type="submit" value="登錄" />
</form>
</body>
</html>
success.jsp
<body>
<h1>歡迎登錄告抄,${user}</h1>
</body>
fail.jsp
<body>
對(duì)不起撰茎,登錄失敗,原因:<br>
${codeErr}
<h2>${errMsg}</h2>
</body>
注:login.jsp的js代碼是完成“點(diǎn)擊更換”功能;注意驗(yàn)證碼的name要和傳入工具類中的名字一樣打洼,src就是生成驗(yàn)證碼的controller路由加上.jpg龄糊。
6、測(cè)試:
輸入正確的驗(yàn)證碼:
登錄成功:
輸入錯(cuò)誤的驗(yàn)證碼:
頁(yè)面顯示驗(yàn)證碼有誤:
點(diǎn)擊驗(yàn)證碼可以更換募疮!
方式二炫惩、在web.xml中配置驗(yàn)證碼:
相比于方式一,一增二減阿浓。
減:
1他嚷、在上面那個(gè)項(xiàng)目的基礎(chǔ)上,把CodeController.java刪掉。
2筋蓖、把spring-kaptcha.xml刪掉卸耘,其他的保留。
增:
1粘咖、在web.xml中添加如下配置:
<!-- 驗(yàn)證碼 -->
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<!-- 是否有邊框 -->
<init-param>
<param-name>kaptcha.border</param-name>
<param-value>no</param-value>
</init-param>
<!-- 字體顏色 -->
<init-param>
<param-name>kaptcha.textproducer.font.color</param-name>
<param-value>black</param-value>
</init-param>
<!-- 圖片寬度 -->
<init-param>
<param-name>kaptcha.image.width</param-name>
<param-value>135</param-value>
</init-param>
<!-- 使用哪些字符生成驗(yàn)證碼 -->
<init-param>
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>ACDEFHKPRSTWX345679</param-value>
</init-param>
<!-- 圖片寬度 -->
<init-param>
<param-name>kaptcha.image.height</param-name>
<param-value>50</param-value>
</init-param>
<!-- 字體大小 -->
<init-param>
<param-name>kaptcha.textproducer.font.size</param-name>
<param-value>43</param-value>
</init-param>
<!-- 干擾線 -->
<init-param>
<param-name>kaptcha.noise.color</param-name>
<param-value>red</param-value>
</init-param>
<!-- 字符個(gè)數(shù) -->
<init-param>
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>4</param-value>
</init-param>
<!-- 字體 -->
<init-param>
<param-name>kaptcha.textproducer.font.names</param-name>
<param-value>Arial</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
注:這段配置就是用來(lái)配置驗(yàn)證碼的蚣抗,注意最后的<url-pattern>/kaptcha.jpg</url-pattern>
要與驗(yàn)證碼中的src = "kaptcha.jpg"
對(duì)應(yīng)。
這樣就完成了驗(yàn)證碼的配置瓮下,接下來(lái)測(cè)試翰铡。
測(cè)試:
輸入錯(cuò)誤的驗(yàn)證碼:
頁(yè)面顯示驗(yàn)證碼錯(cuò)誤:
輸入正確的驗(yàn)證碼:
登錄成功:
測(cè)試通過(guò)!
總結(jié):
1讽坏、在頁(yè)面中加驗(yàn)證碼很簡(jiǎn)單锭魔,只需要添加<img src= "xx">
即可。用一個(gè)img標(biāo)簽路呜,然后通過(guò)src指向生成驗(yàn)證碼的controller的路由加上.jpg(驗(yàn)證碼用spring方式配置)赂毯,或者通過(guò)src指向
<url-pattern>/kaptcha.jpg</url-pattern>
,即src="kaptcha.jpg"
拣宰。
2、點(diǎn)擊更換也簡(jiǎn)單烦感,就是給img標(biāo)簽加一個(gè)onclick事件巡社,然后用js完成。
點(diǎn)擊更換的js:
<script type="text/javascript">
function refresh() {
document.getElementById('captcha_img').src="kaptcha.jpg?"+Math.random();
}
</script>
然后在img標(biāo)簽中加上onclick="refresh()"
手趣,這樣就完成了這個(gè)點(diǎn)擊事件晌该。
3、更多kaptcha屬性的配置绿渣,請(qǐng)參考kaptcha詳細(xì)配置表朝群。