有關jCaptch則是也是先選輕鬆把功能先搞出來的方法。因為信心缺乏症候群,所以先用簡單蠻幹的東西建立信心。信心建立以後在想其他問題。
Listing. cas-server-core pom.xml add jcaptcha dependency
194 |
<GROUPID>com.octo.captcha</GROUPID> |
195 |
<ARTIFACTID>jcaptcha</ARTIFACTID> |
196 |
<VERSION>1.0</VERSION> |
接著根據jcaptch網站『快快樂樂使用jCaptcha』的文章寫一個產生唯一default image captcha service instance的class和產生圖的servlet。程式都是抄jCaptcha網站滴。
Listing. CaptchaServiceSingleton.java
01 |
package org.jasig.cas.captcha; |
03 |
import com.octo.captcha.service.image.ImageCaptchaService; |
04 |
import com.octo.captcha.service.image.DefaultManageableImageCaptchaService; |
06 |
public class CaptchaServiceSingleton { |
07 |
private static ImageCaptchaService instance = new DefaultManageableImageCaptchaService(); |
09 |
public static ImageCaptchaService getInstance() { |
Listing. ImageCaptchaServlet.java
01 |
package org.jasig.cas.captcha; |
03 |
import com.octo.captcha.service.CaptchaServiceException; |
04 |
import com.sun.image.codec.jpeg.JPEGCodec; |
05 |
import com.sun.image.codec.jpeg.JPEGImageEncoder; |
07 |
import javax.servlet.ServletConfig; |
08 |
import javax.servlet.ServletException; |
09 |
import javax.servlet.ServletOutputStream; |
10 |
import javax.servlet.http.HttpServlet; |
11 |
import javax.servlet.http.HttpServletRequest; |
12 |
import javax.servlet.http.HttpServletResponse; |
13 |
import java.awt.image.BufferedImage; |
14 |
import java.io.ByteArrayOutputStream; |
15 |
import java.io.IOException; |
18 |
public class ImageCaptchaServlet extends HttpServlet { |
21 |
public void init(ServletConfig servletConfig) throws ServletException { |
22 |
super.init(servletConfig); |
26 |
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { |
28 |
byte[] captchaChallengeAsJpeg = null; |
30 |
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); |
34 |
String captchaId = httpServletRequest.getSession().getId(); |
36 |
BufferedImage challenge = |
37 |
CaptchaServiceSingleton.getInstance().getImageChallengeForID(captchaId, |
38 |
httpServletRequest.getLocale()); |
41 |
JPEGImageEncoder jpegEncoder = |
42 |
JPEGCodec.createJPEGEncoder(jpegOutputStream); |
43 |
jpegEncoder.encode(challenge); |
44 |
} catch (IllegalArgumentException e) { |
45 |
httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND); |
47 |
} catch (CaptchaServiceException e) { |
48 |
httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); |
52 |
captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); |
55 |
httpServletResponse.setHeader("Cache-Control", "no-store"); |
56 |
httpServletResponse.setHeader("Pragma", "no-cache"); |
57 |
httpServletResponse.setDateHeader("Expires", 0); |
58 |
httpServletResponse.setContentType("image/jpeg"); |
59 |
ServletOutputStream responseOutputStream = |
60 |
httpServletResponse.getOutputStream(); |
61 |
responseOutputStream.write(captchaChallengeAsJpeg); |
62 |
responseOutputStream.flush(); |
63 |
responseOutputStream.close(); |
在cas-server-webapp module裡面要使用captcha servlet就必須在web.xml設定servlet,另外在/WEB-INF/view/jsp/default/ui/casLogingView.jsp這個jsp就可以加上img element就可以看到captcha image。
AuthenticationViaFormAction Modification
蠻幹小胖的手腳是動在submit()這個method,根據jCaptch網站的資訊要使用validateReponseForID()要取得session id,正好在AuthenticationViaForm#doBind()可以看到CAS有寫一個WebUtil class可以從Spring WebFlow的RequestContext中取得HttpServletRequest物件。因此我們可以輕鬆拿來利用一下。
Listing. AuthenticationViaFormAction#submit() captcha validate 程式片段
66 |
final HttpServletRequest request = WebUtils.getHttpServletRequest(context); |
67 |
Boolean isResponseCorrect = Boolean.FALSE; |
68 |
String enterCaptchaId = request.getParameter( "j_captcha_response" ); |
69 |
String captchaId = request.getSession().getId(); |
72 |
isResponseCorrect = CaptchaServiceSingleton.getInstance().validateResponseForID(captchaId, enterCaptchaId); |
73 |
} catch (CaptchaServiceException e) { |
Listing. AuthenticationViaFormAction#submit() 增加流程的程式片段
097 |
if( Boolean.TRUE.equals(isResponseCorrect) ) { |
098 |
WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials)); |
099 |
putWarnCookieIfRequestParameterPresent(context); |