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列表如下图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值