JCAPTCHA integration with CAS

View: New views
3 Messages — Rating Filter:   Alert me  

Parent Message unknown JCAPTCHA integration with CAS

by Axel Mendoza Pupo :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

to integrate JCAPTCHA with CAS some changes has need
 
In the login-webflow.xml:
 
1- Replace the action state bindAndValidate for this
 
<action-state id="bindAndValidate">
<action bean="authenticationViaFormAction" />
<transition on="success" to="captchaCheck" />
<transition on="error" to="errorCount" />
</action-state>
 
2- Replace the action state submit for this
 
<action-state id="submit">
  <action bean="authenticationViaFormAction" method="submit" />
  <transition on="warn" to="warn" />
  <transition on="success" to="sendTicketGrantingTicket" />
  <transition on="error" to="errorCount" />
 </action-state>
 
3-Add the new action states
 
<decision-state id="captchaCheck">
  <if test="${flowScope.count != null && flowScope.count >= 3}" then="captchaValidate" else="submit"/>
 </decision-state>
 
 <action-state id="captchaValidate">
  <action bean="captchaValidateAction" />
  <transition on="success" to="submit" />
  <transition on="error" to="errorCount" />
 </action-state>
 
 <action-state id="errorCount">
  <action bean="captchaErrorCountAction" />
  <transition on="success" to="viewLoginForm" />
 </action-state>
 
//*******************************************************
the code for the action bean CaptchaErrorCountAction
 
import org.jasig.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
 
public final class CaptchaErrorCountAction extends AbstractAction {
 
 protected Event doExecute(final RequestContext context) {
  int count;
  try {  
   count = (Integer)context.getFlowScope().get("count");
 } catch (Exception e) {
   count=0;
 }
   
 count++;
 
 context.getFlowScope().put("count", count);
 
 return success();
 }

}
 
//*******************************************************
the code for the action bean captchaValidateAction
 
import org.jasig.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;

public final class CaptchaValidateAction extends AbstractAction {
 private ImageCaptchaService jcaptchaService;
 private String captchaValidationParameter = "_captcha_parameter";
 protected Event doExecute(final RequestContext context) {
  String captcha_response = context.getRequestParameters().get(captchaValidationParameter);
  boolean valid = false;
 
  if(captcha_response != null){
   String id = WebUtils.getHttpServletRequest(context).getSession().getId();
   if(id != null){
    try {
   valid = jcaptchaService.validateResponseForID(id, response).booleanValue();
  } catch (CaptchaServiceException cse) {  
  }
  }
  }
 
  if(valid){
   return success();
  }
 
  return error();
 }

 public void setCaptchaService(JCaptchaServiceProxy captchaService) {
  this.captchaService = captchaService;
 }
 
 public void setCaptchaValidationParameter(String captchaValidationParameter) {
  this.captchaValidationParameter = captchaValidationParameter;
 }
}
//*******************************************************
 
to generate the captcha image you must add a new controller to send the image in response to your image url
 
//*******************************************************
the code for the controller that process the image url
 
import com.octo.captcha.service.image.ImageCaptchaService;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.io.ByteArrayOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
 
public class CaptchaImageCreateController
    implements Controller, InitializingBean
{
    public CaptchaImageCreateController()
    {
    }
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        byte captchaChallengeAsJpeg[] = null;
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        String captchaId = request.getSession().getId();
        java.awt.image.BufferedImage challenge = jcaptchaService.getImageChallengeForID(captchaId, request.getLocale());
        JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream);
        jpegEncoder.encode(challenge);
        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
        response.setHeader("Cache-Control", "no-store");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0L);
        response.setContentType("image/jpeg");
        ServletOutputStream responseOutputStream = response.getOutputStream();
        responseOutputStream.write(captchaChallengeAsJpeg);
        responseOutputStream.flush();
        responseOutputStream.close();
        return null;
    }
    public void setJcaptchaService(ImageCaptchaService jcaptchaService)
    {
        this.jcaptchaService = jcaptchaService;
    }
    public void afterPropertiesSet()
        throws Exception
    {
        if(jcaptchaService == null)
            throw new RuntimeException("Image captcha service wasn`t set!");
        else
            return;
    }
    private ImageCaptchaService jcaptchaService;
}
//*******************************************************
 
You should configure this controller in cas-servlet.xml and map to the url that the controller will process add the following to the handlerMappingC bean in the property mappings
<prop
     key="/captcha.htm">
     captchaImageCreateController
</prop>
 
/captcha.htm or whatever url that you want to set shoul be map in the web.xml by add the following
 <servlet-mapping>
  <servlet-name>cas</servlet-name>
  <url-pattern>/captcha.htm</url-pattern>
 </servlet-mapping>
 
The last step is the use of this url in our authentication page by add the following JSP code
<c:if test="${not empty count && count >= 3}" >
<img src="captcha.htm" >
<input name="j_captcha_response" type="text">
</c:if>
 
//*******************************************************
the configuration of the beans described here
 
<bean id="captchaErrorCountAction" class="your.path.CaptchaErrorCountAction"/>
 
 <bean id="captchaValidateAction" class="your.path.CaptchaValidateAction"
  p:captchaService-ref="captchaService"
  p:captchaValidationParameter="j_captcha_response"/>
 
<bean id="captchaImageCreateController" class="your.path.CaptchaImageCreateController">
  <property name="jcaptchaService" ref="jcaptchaService" />
 </bean>
 
the configuration of the bean jcaptchaService is bussiness of the developer, the following is an example
<bean id="jcaptchaService" class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService"/>
 
 


_______________________________________________
Yale CAS mailing list
cas@...
http://tp.its.yale.edu/mailman/listinfo/cas

winmail.dat (17K) Download Attachment

Re: JCAPTCHA integration with CAS

by Arnaud Lesueur-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Alex,

Thanks for this integration. Could you submit this in the CAS User Manual ? To keep a better trace of your work ?

I've just look at this integration without making my own practical test. But your count variable is in the flowScope this mean, it is linked to the user session. So an attacker who is removing it's user session between to tentative won't have to defeat your captcha, right ?

Or am I missing something ?

Regards,

Arnaud Lesueur


On Tue, Jun 17, 2008 at 2:41 PM, Axel Mendoza Pupo <apupo@...> wrote:
to integrate JCAPTCHA with CAS some changes has need

In the login-webflow.xml:

1- Replace the action state bindAndValidate for this

<action-state id="bindAndValidate">
<action bean="authenticationViaFormAction" />
<transition on="success" to="captchaCheck" />
<transition on="error" to="errorCount" />
</action-state>

2- Replace the action state submit for this

<action-state id="submit">
 <action bean="authenticationViaFormAction" method="submit" />
 <transition on="warn" to="warn" />
 <transition on="success" to="sendTicketGrantingTicket" />
 <transition on="error" to="errorCount" />
 </action-state>

3-Add the new action states

<decision-state id="captchaCheck">
 <if test="${flowScope.count != null &amp;&amp; flowScope.count >= 3}" then="captchaValidate" else="submit"/>
 </decision-state>

 <action-state id="captchaValidate">
 <action bean="captchaValidateAction" />
 <transition on="success" to="submit" />
 <transition on="error" to="errorCount" />
 </action-state>

 <action-state id="errorCount">
 <action bean="captchaErrorCountAction" />
 <transition on="success" to="viewLoginForm" />
 </action-state>

//*******************************************************
the code for the action bean CaptchaErrorCountAction

import org.jasig.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

public final class CaptchaErrorCountAction extends AbstractAction {

 protected Event doExecute(final RequestContext context) {
 int count;
 try {
  count = (Integer)context.getFlowScope().get("count");
 } catch (Exception e) {
  count=0;
 }

 count++;

 context.getFlowScope().put("count", count);

 return success();
 }

}

//*******************************************************
the code for the action bean captchaValidateAction

import org.jasig.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;

public final class CaptchaValidateAction extends AbstractAction {
 private ImageCaptchaService jcaptchaService;
 private String captchaValidationParameter = "_captcha_parameter";
 protected Event doExecute(final RequestContext context) {
 String captcha_response = context.getRequestParameters().get(captchaValidationParameter);
 boolean valid = false;

 if(captcha_response != null){
  String id = WebUtils.getHttpServletRequest(context).getSession().getId();
  if(id != null){
   try {
  valid = jcaptchaService.validateResponseForID(id, response).booleanValue();
 } catch (CaptchaServiceException cse) {
 }
 }
 }

 if(valid){
  return success();
 }

 return error();
 }

 public void setCaptchaService(JCaptchaServiceProxy captchaService) {
 this.captchaService = captchaService;
 }

 public void setCaptchaValidationParameter(String captchaValidationParameter) {
 this.captchaValidationParameter = captchaValidationParameter;
 }
}
//*******************************************************

to generate the captcha image you must add a new controller to send the image in response to your image url

//*******************************************************
the code for the controller that process the image url

import com.octo.captcha.service.image.ImageCaptchaService;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.io.ByteArrayOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class CaptchaImageCreateController
   implements Controller, InitializingBean
{
   public CaptchaImageCreateController()
   {
   }
   public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
       throws Exception
   {
       byte captchaChallengeAsJpeg[] = null;
       ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
       String captchaId = request.getSession().getId();
       java.awt.image.BufferedImage challenge = jcaptchaService.getImageChallengeForID(captchaId, request.getLocale());
       JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream);
       jpegEncoder.encode(challenge);
       captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
       response.setHeader("Cache-Control", "no-store");
       response.setHeader("Pragma", "no-cache");
       response.setDateHeader("Expires", 0L);
       response.setContentType("image/jpeg");
       ServletOutputStream responseOutputStream = response.getOutputStream();
       responseOutputStream.write(captchaChallengeAsJpeg);
       responseOutputStream.flush();
       responseOutputStream.close();
       return null;
   }
   public void setJcaptchaService(ImageCaptchaService jcaptchaService)
   {
       this.jcaptchaService = jcaptchaService;
   }
   public void afterPropertiesSet()
       throws Exception
   {
       if(jcaptchaService == null)
           throw new RuntimeException("Image captcha service wasn`t set!");
       else
           return;
   }
   private ImageCaptchaService jcaptchaService;
}
//*******************************************************

You should configure this controller in cas-servlet.xml and map to the url that the controller will process add the following to the handlerMappingC bean in the property mappings
<prop
    key="/captcha.htm">
    captchaImageCreateController
</prop>

/captcha.htm or whatever url that you want to set shoul be map in the web.xml by add the following
 <servlet-mapping>
 <servlet-name>cas</servlet-name>
 <url-pattern>/captcha.htm</url-pattern>
 </servlet-mapping>

The last step is the use of this url in our authentication page by add the following JSP code
<c:if test="${not empty count && count >= 3}" >
<img src="captcha.htm" >
<input name="j_captcha_response" type="text">
</c:if>

//*******************************************************
the configuration of the beans described here

<bean id="captchaErrorCountAction" class="your.path.CaptchaErrorCountAction"/>

 <bean id="captchaValidateAction" class="your.path.CaptchaValidateAction"
 p:captchaService-ref="captchaService"
 p:captchaValidationParameter="j_captcha_response"/>

<bean id="captchaImageCreateController" class="your.path.CaptchaImageCreateController">
 <property name="jcaptchaService" ref="jcaptchaService" />
 </bean>

the configuration of the bean jcaptchaService is bussiness of the developer, the following is an example
<bean id="jcaptchaService" class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService"/>



_______________________________________________
Yale CAS mailing list
cas@...
http://tp.its.yale.edu/mailman/listinfo/cas




--
Arnaud Lesueur

LinkedIn: http://www.linkedin.com/in/lesueur
_______________________________________________
Yale CAS mailing list
cas@...
http://tp.its.yale.edu/mailman/listinfo/cas

Parent Message unknown Re: JCAPTCHA integration with CAS

by Axel Mendoza Pupo :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

you are right, but if an attacker use a different session in every authentication request, for CAS is a diferent user who is trying to authenticate or not ?, so I think that this case is bussiness of a superior check like a filter that count the bad authentication request of that IP address and denied request from blocked IP address to keep safe CAS from brute force.


_______________________________________________
Yale CAS mailing list
cas@...
http://tp.its.yale.edu/mailman/listinfo/cas

winmail.dat (3K) Download Attachment