Portal Showcase


You can choose between SimpleCaptcha and ReCaptcha implementations by modifying the value of the captcha.engine.impl property in your portal-ext.properties file.

When running in Liferay Portal 7.0 (and above), an authenticated user will be considered trustworthy after entering a correct value a certain number of times, which is known as the maximum number of challenges. The maximum is defined by the captcha.max.challenges property in your portal-ext.properties file, which is 1 by default. When an authenticated user has gained the necessary level of trust, the Captcha will no longer be rendered (or required) for the remainder of the session. Non-authenticated users will never be considered trustworthy, and will always be required enter a correct value for the Captcha, provided that the value of the required property is true.

For more information, see the default values in the "Captcha" section of Liferay Portal's portal.properties file and LPS-40401.


Captcha is a UIInput that renders Liferay Portal's captcha image and a field for editing single-line text. It provides built-in validation in order to make sure that the text value entered by the user matches the value in the captcha image.

General Usage

The value attribute can be bound to a model bean property via EL.

Source Code

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
	xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:h="http://xmlns.jcp.org/jsf/html"

	<h:form id="f1">
		<h:messages layout="table" />
		<portal:captcha id="simpleCaptcha" required="#{showcaseModelBean.selectedComponent.required}"
			value="#{captchaBacking.captchaText}" />
		<h:commandButton action="#{captchaBacking.submit}" value="#{i18n['submit']}">
			<f:ajax execute="@form" render="@form :modelValue" />
	<h:outputText id="modelValue" value="#{captchaBacking.captchaText}" />

public class CaptchaBacking {

	@ManagedProperty(value = "#{showcaseModelBean.selectedComponent.required}")
	private boolean requiredChecked;

	private String captchaText;

	public String getCaptchaImpl() {
		return CaptchaUtil.getCaptcha().getClass().getName();

	public String getCaptchaText() {
		return captchaText;

	public boolean isRequiredChecked() {
		return requiredChecked;

	public void setCaptchaText(String captchaText) {
		this.captchaText = captchaText;

	public void setRequiredChecked(boolean requiredChecked) {

		// Injected via @ManagedProperty
		this.requiredChecked = requiredChecked;

	public void submit() {

		FacesContext facesContext = FacesContext.getCurrentInstance();
		ExternalContext externalContext = facesContext.getExternalContext();
		FacesContextHelper facesContextHelper = FacesContextHelperFactory.getFacesContextHelperInstance(

		// If the user entered non-blank value for the captcha then validation was successful in the
		// PROCESS_VALIDATIONS phase of the JSF lifecycle.
		if ((captchaText != null) && (captchaText.trim().length() > 0)) {

			facesContextHelper.addGlobalInfoMessage(facesContext, "you-entered-the-correct-text-verification-code");

		// Otherwise, the user entered a blank value for the captcha.
		else {

			// If the user checked the "Required" checkbox, then
			if (requiredChecked) {

				// If the portal:captcha component indicates that the value is required, then validation should have
				// failed in the PROCESS_VALIDATIONS phase of the JSF lifecycle and this method should never have been
				// called now in the INVOKE_APPLICATION phase. This indicates an error condition that should never
				// happen.
				UIViewRoot uiViewRoot = facesContext.getViewRoot();
				Captcha captcha = (Captcha) uiViewRoot.findComponent(":f1:simpleCaptcha");

				if (captcha.isRequired()) {


				// Otherwise, if the portal:captcha component indicates that the value is not required, then according
				// to the JavaDoc for the required attribute, that means the captcha was "inactive" because an
				// authenticated user has correctly entered the captcha the maximum number of required times. This does
				// not indicate an error condition.
				else {

					String maxChallenges = PropsUtil.get(PropsKeys.CAPTCHA_MAX_CHALLENGES);

			// Otherwise, since the user did not check the "Required" checkbox, it's OK that the user entered a blank
			// value.
			else {

Liferay Faces Bridge Implementation 4.1.0 + Liferay Faces Portal 3.0.2-SNAPSHOT + Showcase Common 3.0.1 + Liferay Faces Util 3.1.0 + Mojarra 2.2.17