`

Spring+Hibernate+JSF+Ajax4jsf+Acegi+jCaptcha 做登录模块

阅读更多

出自:http://yingongong.blog.163.com/blog/static/492197620080893610377/

带图片验证码的用户登录是一个系统中很常见的模块,在Java EE中有很多不同的实现,而开源世界中又给我们提供了很多优秀的框架,从而减少了我们的编码量,下面给大家简单介绍一下用Spring+Hibernate+JSF+Ajax4jsf+Acegi+jCaptcha 如何构建一个登录模块:

    我使用这些框架的版本如下:

    Spring 2.0.1

    Hibernate 3.2

    JSF 1.2

    Acegi 1.0.5

    jCaptcha 1.0-RC6

    首先建表USERTEST,和ROLETEST,作为用户表和角色表

CREATE TABLE USERTEST

(

  USERID    NUMBER                              NOT NULL,

  USERNAME  VARCHAR2(20 CHAR)                   NOT NULL,

  PASSWORD  VARCHAR2(100 CHAR)                  NOT NULL,

  STATUS    NUMBER                              DEFAULT 1                     NOT NULL,

  ROLEID    NUMBER                              NOT NULL

)

CREATE TABLE ROLETEST

(

  ROLEID    NUMBER                              NOT NULL,

  ROLENAME  VARCHAR2(50 CHAR)                   NOT NULL,

  ROLEDESC  VARCHAR2(50 CHAR)

)

    同时给ROLETEST表添加一条记录:1    ROLE_USER    普通用户

    再给USERTEST表添加一条记录:1    admin    123    1    1

    对应的hbm.xml文件就相信大家都会写,如果用eclipse开发的话,可以使用HibernateSynchronizer插件,我使用的版本是3.1.9

    接下来就要给web.xml的配置一下了:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns="http://java.sun.com/xml/ns/javaee"

 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

 id="WebApp_ID" version="2.5">

 <display-name>Demo</display-name>

 <welcome-file-list>

  <welcome-file>index.html</welcome-file>

  <welcome-file>index.htm</welcome-file>

  <welcome-file>index.jsp</welcome-file>

 </welcome-file-list>

 <context-param>

  <param-name>contextConfigLocation</param-name>

  <param-value>

   /WEB-INF/classes/applicationContext.xml

  </param-value>

 </context-param>

 <context-param>

  <param-name>javax.faces.CONFIG_FILES</param-name>

  <param-value>/WEB-INF/faces-config.xml</param-value>

 </context-param>

 <listener>

  <listener-class>

   org.springframework.web.context.ContextLoaderListener

  </listener-class>

 </listener>

 <listener>

  <listener-class>

   org.acegisecurity.ui.session.HttpSessionEventPublisher

  </listener-class>

 </listener>

 <listener>

  <listener-class>

   com.sun.faces.config.ConfigureListener

  </listener-class>

 </listener>

 <filter>

  <filter-name>OpenSessionInView</filter-name>

  <filter-class>

   org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

  </filter-class>

  <init-param>

   <param-name>singleSession</param-name>

   <param-value>true</param-value>

  </init-param>

 </filter>

 <filter-mapping>

  <filter-name>OpenSessionInView</filter-name>

  <url-pattern>*.jsf</url-pattern>

 </filter-mapping>

 <filter>

  <filter-name>Acegi Filter Chain Proxy</filter-name>

  <filter-class>

   org.acegisecurity.util.FilterToBeanProxy

  </filter-class>

  <init-param>

   <param-name>targetClass</param-name>

   <param-value>

    org.acegisecurity.util.FilterChainProxy

   </param-value>

  </init-param>

 </filter>

 <filter-mapping>

  <filter-name>Acegi Filter Chain Proxy</filter-name>

  <url-pattern>/*</url-pattern>

  <dispatcher>FORWARD</dispatcher>

  <dispatcher>REQUEST</dispatcher>

 </filter-mapping>

 <filter>

  <display-name>Ajax4jsf Filter</display-name>

  <filter-name>ajax4jsf</filter-name>

  <filter-class>org.ajax4jsf.Filter</filter-class>

  </filter>

 

  <filter-mapping>

  <filter-name>ajax4jsf</filter-name>

  <servlet-name>Faces Servlet</servlet-name>

  <dispatcher>REQUEST</dispatcher>

  <dispatcher>FORWARD</dispatcher>

  <dispatcher>INCLUDE</dispatcher>

  </filter-mapping>

 

 

 <servlet>

  <servlet-name>Faces Servlet</servlet-name>

  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

  <load-on-startup>1</load-on-startup>

 </servlet>

 <servlet-mapping>

  <servlet-name>Faces Servlet</servlet-name>

  <url-pattern>*.jsf</url-pattern>

 </servlet-mapping>

 </web-app>

    然后Spring的applicationContext.xml,在这里面你需要配置数据库连接、hibernate的各种策略、Acegi安全设置、jCaptcha设置等等:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns:aop="http://www.springframework.org/schema/aop"

 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.1.xsd">

 <bean id="dataSource"

  class="org.apache.commons.dbcp.BasicDataSource">

  <property name="driverClassName">

   <value>oracle.jdbc.driver.OracleDriver</value>

  </property>

  <property name="url">

   <value>jdbc:oracle:thin:@10.10.10.10:1521:demo</value>

  </property>

  <property name="username">

   <value>demo</value>

  </property>

  <property name="password">

   <value>demo</value>

  </property>

 </bean>

 <bean id="sessionFactory"

  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

  <property name="dataSource">

   <ref bean="dataSource" />

  </property>

  <property name="hibernateProperties">

   <props>

    <prop key="hibernate.dialect">

     org.hibernate.dialect.OracleDialect

    </prop>

    <prop key="hibernate.connection.pool_size">5</prop>

    <prop key="hibernate.show_sql">true</prop>

    <prop key="cache.provider_class">

     org.hibernate.cache.OSCacheProvider

    </prop>

    <prop key="cache.use_query_cache">true</prop>

    <prop key="cglib.use_reflection_optimizer">false</prop>

   </props>

  </property>

  <property name="mappingDirectoryLocations">

   <list><!-- 这里指定了hibernate的映射目录 -->

    <value>classpath:/com/fifthlab/demo/pojo</value>

   </list>

  </property>

 </bean>

 <bean id="transactionManager"

  class="org.springframework.orm.hibernate3.HibernateTransactionManager">

  <property name="sessionFactory" ref="sessionFactory" />

 </bean>

 <!-- Transaction template for Managers -->

 <bean id="txProxyTemplate" abstract="true"

  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

  <property name="transactionManager" ref="transactionManager" />

  <property name="transactionAttributes">

   <props>

    <prop key="save*">PROPAGATION_REQUIRED</prop>

    <prop key="add*">PROPAGATION_REQUIRED</prop>

    <prop key="delete*">PROPAGATION_REQUIRED</prop>

    <prop key="update*">PROPAGATION_REQUIRED</prop>

    <prop key="relation*">PROPAGATION_REQUIRED</prop>

    <prop key="disconnect*">PROPAGATION_REQUIRED</prop>

    <prop key="assign*">PROPAGATION_REQUIRED</prop>

    <prop key="unassign*">PROPAGATION_REQUIRED</prop>

    <prop key="*">PROPAGATION_SUPPORTS</prop>

   </props>

  </property>

 </bean>

<!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX acegi part begin XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->

 <!-- ======================== FILTER CHAIN ======================= -->

 <!--  if you wish to use channel security, add "channelProcessingFilter," in front

  of "httpSessionContextIntegrationFilter" in the list below -->

 <bean id="filterChainProxy"

  class="org.acegisecurity.util.FilterChainProxy">

  <property name="filterInvocationDefinitionSource">

   <value>

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON

    PATTERN_TYPE_APACHE_ANT

    /**/*.jsf=httpSessionContextIntegrationFilter,captchaValidationProcessingFilter,authenticationProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor

   </value>

  </property>

 </bean>

 <bean id="httpSessionContextIntegrationFilter"

  class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">

  <property name="context">

   <value><!-- 此处修复了Acegi和jCaptcha不能兼容的一个bug,在后面的版本中应该修复了 -->

    com.fifthlab.demo.dao.authentication.FixedCaptchaSecurityContextImpl

   </value>

  </property>

 </bean>

 <bean id="authenticationManager"

  class="org.acegisecurity.providers.ProviderManager">

  <property name="providers">

   <list>

    <ref local="daoAuthenticationProvider" />

   </list>

  </property>

 </bean>

 <bean id="daoAuthenticationProvider"

  class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">

  <property name="userDetailsService">

   <ref local="hibernate3Authentication" />

  </property>

 </bean>

 <bean id="loggerListener"

  class="org.acegisecurity.event.authentication.LoggerListener" />

 <bean id="authenticationProcessingFilter"

  class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">

  <property name="authenticationManager">

   <ref bean="authenticationManager" />

  </property>

  <property name="authenticationFailureUrl">

   <value>/login.jsf</value>

  </property>

  <property name="defaultTargetUrl">

   <value>/login.jsf</value>

  </property>

  <property name="filterProcessesUrl">

   <value>/j_acegi_security_check</value>

  </property>

 </bean>

 <bean id="exceptionTranslationFilter"

  class="org.acegisecurity.ui.ExceptionTranslationFilter">

  <property name="authenticationEntryPoint">

   <ref local="authenticationProcessingFilterEntryPoint" />

  </property>

 </bean>

 <bean id="authenticationProcessingFilterEntryPoint"

  class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">

  <property name="loginFormUrl">

   <value>/login.jsf</value>

  </property>

  <property name="forceHttps">

   <value>false</value>

  </property>

 </bean>

 <bean id="filterInvocationInterceptor"

  class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">

  <property name="authenticationManager">

   <ref bean="authenticationManager" />

  </property>

  <property name="accessDecisionManager">

   <ref local="httpRequestAccessDecisionManager" />

  </property>

  <property name="observeOncePerRequest">

   <value>true</value>

  </property>

  <property name="objectDefinitionSource">

   <value>

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON

    PATTERN_TYPE_APACHE_ANT

    /login.jsp=ROLE_ANONYMOUS

    /success.jsp=ROLE_USER

   </value>

  </property>

 </bean>

 <!-- 用来验证用户名密码是否相符,并赋予相应的角色 -->

 <bean id="hibernate3Authentication"

  class="com.fifthlab.demo.dao.authentication.Hibernate3Authentication">

  <property name="sessionFactory">

   <ref local="sessionFactory" />

  </property>

 </bean>

 <bean id="anonymousProcessingFilter"

  class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">

  <property name="key">

   <value>foobar</value>

  </property>

  <property name="userAttribute">

   <value>anonymousUser,ROLE_ANONYMOUS</value>

  </property>

 </bean>

 <bean id="httpRequestAccessDecisionManager"

  class="org.acegisecurity.vote.AffirmativeBased">

  <property name="allowIfAllAbstainDecisions">

   <value>false</value>

  </property>

  <property name="decisionVoters">

   <list>

    <ref bean="roleVoter" />

   </list>

  </property>

 </bean>

 <bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter" />

<!-- 下面开始添加 jcaptcha  -->

<bean id="captchaValidationProcessingFilter"

  class="org.acegisecurity.captcha.CaptchaValidationProcessingFilter">

  <property name="captchaService">

   <ref bean="captchaService" />

  </property>

  <property name="captchaValidationParameter">

   <value>j_captcha_response</value>

  </property>

 </bean>

 <!-- 用来验证图片验证码是否输入正确 --><bean id="captchaService"

  class="com.fifthlab.demo.dao.authentication.JCaptchaServiceProxyImpl">

  <property name="jcaptchaService" ref="jcaptchaService" />

 </bean>

 <bean id="jcaptchaService"

  class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService" />

 <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX acegi part end XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->

</beans>

    先解释一下上面applicationContext.xml中红色的部分是jCaptcha的一个filter,必须放在第二个位置,后面的是acegi的filter,也就是说,要先验证图片验证码是否正确,再让acegi来验证用户名和密码。蓝色的部分是需要写的几个代码,其中有一个修复bug的地方,如果不添加那个bean,在运行的时候就会报Cast转型的错误。下面列一下蓝色部分的代码:

FixedCaptchaSecurityContextImpl:

import org.acegisecurity.captcha.CaptchaSecurityContextImpl;

public class FixedCaptchaSecurityContextImpl extends CaptchaSecurityContextImpl {

 public int hashCode() {

  if (getAuthentication() == null) {

   return (int) System.currentTimeMillis();

  } else {

   return this.getAuthentication().hashCode();

  }

 }

}

Hibernate3Authentication:

import java.util.ArrayList;

import java.util.List;

import org.acegisecurity.GrantedAuthority;

import org.acegisecurity.GrantedAuthorityImpl;

import org.acegisecurity.userdetails.UserDetails;

import org.acegisecurity.userdetails.UserDetailsService;

import org.acegisecurity.userdetails.UsernameNotFoundException;

import org.hibernate.Criteria;

import org.hibernate.criterion.Expression;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.fifthlab.demo.pojo.Roletest;

import com.fifthlab.demo.pojo.Usertest;

public class Hibernate3Authentication extends HibernateDaoSupport implements UserDetailsService {

 public UserDetails loadUserByUsername(final String username)

 {

  Criteria criteria = getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(Usertest.class);

  criteria.add(Expression.eq(Usertest.PROP_USERNAME, username));

  List users = criteria.list();

  if (users.size() == 0)

  {

   throw new UsernameNotFoundException("User not found");

  }

  Usertest user = (Usertest) users.get(0);

  // get User roles of this user

  List<Roletest> userRoles = new ArrayList<Roletest>();

  userRoles.add(user.getRoletest());

  GrantedAuthority[] dbAuths = new GrantedAuthority[userRoles.size()];

  if (userRoles.size() == 0)

  {

   throw new UsernameNotFoundException("User has no GrantedAuthority");

  }

  // grant authority to user

  String roleName = null;

  Roletest role = null;

  for (int i = 0; i < userRoles.size(); i++)

  {

   role = (Roletest) userRoles.get(i);

   if (null != role)

   {

    roleName = role.getRolename();

    dbAuths[i] = new GrantedAuthorityImpl(roleName);    

   }

  }

  

  user.setAuthorities(dbAuths);

  

  return user;

 }

}

JCaptchaServiceProxyImpl:

import org.acegisecurity.captcha.CaptchaServiceProxy;

import com.octo.captcha.service.image.ImageCaptchaService;

import com.octo.captcha.service.CaptchaServiceException;

public class JCaptchaServiceProxyImpl implements CaptchaServiceProxy {

   

    private ImageCaptchaService jcaptchaService;

 

    public boolean validateReponseForId(String id, Object response) {

 

      try {

       boolean result = jcaptchaService.validateResponseForID(id, response);

       //System.out.println("id:"+id+"\nresponse:"+response+"\nresult:"+result);

       return result;

 

      } catch (CaptchaServiceException cse) {

        //fixes known bug in JCaptcha

       cse.printStackTrace();

        return false;

      }

    }

 

    public void setJcaptchaService(ImageCaptchaService jcaptchaService) {

      this.jcaptchaService = jcaptchaService;

    }

  }

    接下来是简单的登录页面login.jsp和登录成功后的跳转页面success.jsp:

login.jsp:

<%@ page language="Java" contentType="text/html;charset=utf-8"%>

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>

<%@ taglib uri="https://ajax4jsf.dev.java.net/ajax" prefix="a4j"%>

<f:view>

 <html>

 <head>

 <title>hello</title>

 </head>

 <META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">

 <META HTTP-EQUIV="Pragma" CONTENT="no-cache">

 <META HTTP-EQUIV="Expires" CONTENT="Expires">

 <body>

 <h:form id="form1">

  <h:panelGrid columns="1">

   <h:panelGroup>

    <h:outputLabel value="username:" for="username" />

    <h:inputText id="username" value="#{loginBean.userName}" />

   </h:panelGroup>

   <h:panelGroup>

    <h:outputLabel value="password:" for="password" />

    <h:inputSecret id="password" value="#{loginBean.password}" />

   </h:panelGroup>

   <h:panelGroup>

    <h:outputLabel value="verifying code:" for="verifyingCode" />

    <h:inputText id="verifyingCode" value="#{loginBean.verifyingCode}" />

    <a4j:mediaOutput element="img" cacheable="false" session="false"

        createContent="#{captchaImageBean.paint}" id="showPic"

        mimeType="image/jpeg" />

    <a4j:commandLink reRender="showPic" requestDelay="40" >

     <h:outputText value="refresh" />

    </a4j:commandLink>

   </h:panelGroup>

   <h:panelGroup>

    <h:commandButton id="commandButton1" value="Submit"

     action="#{loginBean.authenticate}" />

   </h:panelGroup>

  </h:panelGrid>

 </h:form>

 </body>

 </html>

</f:view>

    其中红色部分是应用了Ajax4jsf这个框架的两个标签,<a4j:mediaOutput> 是表示输出一个媒体,这里我选择的是输出图片,它会异步的产生图片,而不必和页面载入时同步取图片。而<a4j:commandLink reRender="showPic"> 则是在看不清图片的情况下通过异步的方式刷新上面那个<a4j:mediaOutput>的图片。

    success.jsp的页面很简单,就是显示一个“Welcome here”的字样,因此不列出来了。

    然后我们看一下页面中用到的backing bean的代码:

LoginBean:

import javax.faces.context.FacesContext;

import javax.servlet.http.HttpSession;

import org.acegisecurity.Authentication;

import org.acegisecurity.AuthenticationException;

import org.acegisecurity.AuthenticationManager;

import org.acegisecurity.context.SecurityContext;

import org.acegisecurity.context.SecurityContextHolder;

import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.fifthlab.demo.dao.authentication.JCaptchaServiceProxyImpl;

public class LoginBean extends HibernateDaoSupport {

 private static final long serialVersionUID = 1L;

 private String userName;

 private String password;

 private String verifyingCode;

 private AuthenticationManager authenticationManager;

 private JCaptchaServiceProxyImpl captchaService;

 /**

  * @return 返回用户输入的验证码

  */

 public String getVerifyingCode()

 {

  return this.verifyingCode;

 }

 

 /**

  * @param verifyingCode 设置图片验证码

  */

 public void setVerifyingCode(String verifyingCode)

 {

  this.verifyingCode = verifyingCode;

 }

 

 /**

  * @return 返回captchaService来验证图片验证码

  */

 public JCaptchaServiceProxyImpl getCaptchaService()

 {

  return this.captchaService;

 }

 

 /**

  * @param captchaService 设置图片验证码服务

  */

 public void setCaptchaService(JCaptchaServiceProxyImpl captchaService)

 {

  this.captchaService = captchaService;

 }

 

 /**

  * @return 返回密码

  */

 public String getPassword()

 {

  return password;

 }

 /**

  * @param password 设置密码

  *           

  */

 public void setPassword(String password)

 {

  this.password = password;

 }

 /**

  * @return 返回用户名

  */

 public String getUserName()

 {

  return userName;

 }

 /**

  * @param userName 设置用户名

  *           

  */

 public void setUserName(String userName)

 {

  this.userName = userName;

 }

 /**

  * @return 返回验证管理器

  */

 public AuthenticationManager getAuthenticationManager()

 {

  return authenticationManager;

 }

 /**

  * @param authenticationManager 设置验证管理器

  *           

  */

 public void setAuthenticationManager(AuthenticationManager authenticationManager)

 {

  this.authenticationManager = authenticationManager;

 }

 

 public String authenticate()

 {

  try

  {

   String sessionid = ((HttpSession)FacesContext.getCurrentInstance()

           .getExternalContext()

           .getSession(false)).getId();

   boolean captchaResult = getCaptchaService().validateReponseForId(sessionid, getVerifyingCode());//验证图片验证码

     UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(

     getUserName(), getPassword());

   //验证用户名和密码

   Authentication auth = getAuthenticationManager().authenticate(authReq);

   String result = "failure";

   if(auth.isAuthenticated() == true && captchaResult)

   {//如果图片验证码和帐户全部验证通过

    result = "succeed";

    //把验证信息保存的上下文中

    SecurityContext secCtx = SecurityContextHolder.getContext();

    secCtx.setAuthentication(auth);

   }

      

   return result;

  }

  catch(AuthenticationException e)

  {

   e.printStackTrace();

   return "failure";

  }

 }

}

CaptchaImageBean:

import java.awt.image.BufferedImage;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import javax.faces.context.FacesContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import com.octo.captcha.service.image.ImageCaptchaService;

import com.sun.image.codec.jpeg.JPEGCodec;

import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class CaptchaImageBean {

 static final long serialVersionUID = 1L;

 private ImageCaptchaService jcaptchaService;

 

 public void setJcaptchaService(ImageCaptchaService jcaptchaService) {

  this.jcaptchaService = jcaptchaService;

 }

 

 public void paint(OutputStream out, Object data) throws IOException

 {

  byte[] captchaChallengeAsJpeg = null;

  ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();

  

  HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance()

        .getExternalContext().getRequest();

  

  String captchaId = ((HttpSession)FacesContext.getCurrentInstance()

    .getExternalContext()

    .getSession(false)).getId();

  

  BufferedImage challenge = jcaptchaService.getImageChallengeForID(

    captchaId, request.getLocale());

  JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream);

  jpegEncoder.encode(challenge);

  captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

  

  jpegOutputStream.close();

  out.write(captchaChallengeAsJpeg);

  out.flush();

  out.close();

 }

}

    最后当然是配置faces-config.xml了,里面配置了和Spring的整合、导航、managed bean等等:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

 <application>

  <variable-resolver>

   org.springframework.web.jsf.DelegatingVariableResolver

  </variable-resolver>

 </application>

 <managed-bean>

  <managed-bean-name>loginBean</managed-bean-name>

  <managed-bean-class>com.fifthlab.demo.backingbean.LoginBean</managed-bean-class>

  <managed-bean-scope>request</managed-bean-scope>

  <managed-property>

   <property-name>authenticationManager</property-name>

   <value>#{authenticationManager}</value>

  </managed-property>

  <managed-property>

   <property-name>captchaService</property-name>

   <value>#{captchaService}</value>

  </managed-property>

 </managed-bean>

 

 <managed-bean>

  <managed-bean-name>captchaImageBean</managed-bean-name>

  <managed-bean-class>com.fifthlab.demo.backingbean.CaptchaImageBean</managed-bean-class>

  <managed-bean-scope>request</managed-bean-scope>

  <managed-property>

   <property-name>jcaptchaService</property-name>

   <value>#{jcaptchaService}</value>

  </managed-property>

 </managed-bean>

 

 <navigation-rule>

  <from-view-id>/login.jsp</from-view-id>

  <navigation-case>

   <from-outcome>succeed</from-outcome>

   <to-view-id>/success.jsp</to-view-id>

  </navigation-case>

  <navigation-case>

   <from-outcome>failure</from-outcome>

   <to-view-id>/login.jsp</to-view-id>

  </navigation-case>

 </navigation-rule>

</faces-config>

    大功告成!让我们来看一下演示吧:

    填好帐户和验证码后,点击Submit,如果失败则还是该页不变,如果成功则跳转到:

    不知道大家有没有实验成功?有任何问题可以给我留言!

P.S. 需要的各种lib列表如下图:

分享到:
评论

相关推荐

    良葛格java学习笔记

    常見程式演算,電腦圖學入門,設計模式,C 語言,GTK,C++,Qt3,Qt4,,Java (上),Java (下),JSP/Servlet,JSF,Ajax,JUnit,Struts,Spring,Hibernate,Acegi

    J2EE 就业秘笈J2EE面试

    - Spring Security或Acegi安全框架 - Spring Boot快速开发 **7. JSF(JavaServer Faces)** JSF是Java EE中的另一种UI组件模型,关注点包括: - UI组件、事件处理、转换和验证 - Managed Beans和Facelets模板 - JSF...

    AJAX学习资料之-DWR中文手册

    ### AJAX学习资料之-DWR中文手册 #### 一、引言与背景介绍 随着Web 2.0技术的兴起,Ajax作为一种重要的前端技术受到了广泛关注。它不仅提升了用户体验,还简化了开发过程。对于想要深入了解Ajax及其相关技术的...

    J2EEWeb应用程序的分析与设计

    标题和描述概述的知识点主要集中在J2EE Web应用程序的分析与设计上,涉及到了Web应用程序的架构、技术栈的选择、框架应用(包括Struts、Spring、Hibernate、Acegi、Ajax等),以及如何通过这些框架和技术增强应用...

    dwr中文手册

    DWR可以与多种Java EE框架进行整合,如Spring、JSF、Struts、WebLogic、Hibernate、WebWork和Acegi等。 ##### 3.1 DWR与Spring 整合DWR与Spring通常需要配置SpringCreator,以便DWR可以从Spring容器中获取服务对象...

    DWR中文文档.pdf

    - **后端集成**:DWR支持与多种服务器端技术(如Spring、Struts、JSF、Hibernate)集成,便于创建复杂的企业级应用。 - **跨域请求**:DWR支持跨域请求处理,使得不同域之间的资源调用成为可能。 #### 三、DWR核心...

    dwr中文开发指南文档

    - **DWR**(Direct Web Remoting)是一种简化Ajax开发的技术框架,它可以让客户端JavaScript直接调用服务器端的Java方法,从而大大简化了Ajax开发过程中的复杂度。 #### 二、DWR与Ajax的关系 - DWR是构建在**Ajax**...

    DWR介绍

    - **插件配置**:允许扩展DWR的功能,例如集成Spring、Hibernate等框架。 - **测试模式配置**:开启测试模式可以帮助开发者更方便地进行单元测试。 ##### 2.2 dwr.xml配置 - **纵览**:`dwr.xml`是DWR的主要配置...

    dwr中文文档

    **DWR**(Direct Web Remoting)是一种简化Ajax编程的技术框架,它使得JavaScript能够直接访问服务器端的Java方法,从而实现了更为简单高效的Ajax开发模式。DWR的核心优势在于简化了前端与后端之间的通信流程,使...

    java开源包4

    Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...

Global site tag (gtag.js) - Google Analytics