首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

myfaces1.x,seam1.2.1跟spring security 2.0(acegi)的集成

2012-11-18 
myfaces1.x,seam1.2.1和spring security 2.0(acegi)的集成acegi升级为spring security2.0后配置有很大不同

myfaces1.x,seam1.2.1和spring security 2.0(acegi)的集成
acegi升级为spring security2.0后配置有很大不同,按照老的配置方式需要更改很多包路径,以及属性名,这需要在源代码中查找,如果配置好是没有问题的。新的配置是基于老的方式并进行了简化,就直接给出我的配置作为参考:
新的配置方式:

<beans xmlns="http://www.springframework.org/schema/beans"  xmlns:security="http://www.springframework.org/schema/security"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd              http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">  <security:http auto-config="true" access-denied-page="/login.faces"><security:intercept-url pattern="/jsp/*/yourpath" access="ROLE_COMMISSAR, ROLE_DRAFTOFFICE, ROLE_TRANSACT, ROLE_DRAFTSUPER, ROLE_URGER"/><security:intercept-url pattern="/jsp/*/yourpath" access="ROLE_LETTERPUBLIC,ROLE_LETTERTRANSACT,ROLE_LETTERTASTER,ROLE_LETTERPROCESS"/><security:intercept-url pattern="/jsp/*/yourpath" access="ROLE_POPULARSUBMIT,ROLE_POPULARPROCESS"/><security:intercept-url pattern="/**/*.gif" access="IS_AUTHENTICATED_ANONYMOUSLY"/><security:intercept-url pattern="/**/*.gif" access="IS_AUTHENTICATED_ANONYMOUSLY"/><security:intercept-url pattern="/**/*.jpg" access="IS_AUTHENTICATED_ANONYMOUSLY"/><security:intercept-url pattern="/**/*.css" access="IS_AUTHENTICATED_ANONYMOUSLY"/><security:intercept-url pattern="/login.faces" access="IS_AUTHENTICATED_ANONYMOUSLY"/><security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /><security:form-login default-target-url="/"always-use-default-target="true"login-page="/login.faces"login-processing-url="/j_spring_security_check"authentication-failure-url="/login.faces" /><security:anonymous key="doesNotMatter" username="anonymousUser"/> <security:concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="false"expired-url="/login.faces"/><security:logout logout-url="/j_spring_security_logout" logout-success-url="/login.faces" /></security:http><security:authentication-provider><security:jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT USER_, PASSWORD_, SIGN_ FROM ORM_USER WHERE USER_= ?"authorities-by-username-query="select user0_.USER_ as col_0_0_, role2_.VALUE_ as col_1_0_ from ORM_USER user0_  inner join ORM_USER_ROLE roles1_ on user0_.ID_=roles1_.USERID_ inner join ORM_ROLE role2_ on roles1_.ROLEID_=role2_.ID_ where user0_.USER_=?"cache-ref="userCache"/></security:authentication-provider><bean id="userCache" /><!-- <bean id="customAuthenticationFilter" name="code">public String login() throws IOException, ServletException    {        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();                RequestDispatcher dispatcher = ((ServletRequest) context.getRequest())                 .getRequestDispatcher("/j_spring_security_check");         dispatcher.forward((ServletRequest) context.getRequest(),                (ServletResponse) context.getResponse());        FacesContext.getCurrentInstance().responseComplete();        // It's OK to return null here because Faces is just going to exit.        logger.debug("=================================================" +         ((HttpServletRequest)context.getRequest()).getSession().getId());        HttpSession session = ((HttpServletRequest)context.getRequest()).getSession();//        session.setAttribute(LOGIN_PROCESS, new Boolean(true));       //这是调整seam的集成部分ContextControl.instance().begin(session);//createAuthData(session, user);        return null;    }public String logout() throws IOException, ServletException    {        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();         RequestDispatcher dispatcher = ((ServletRequest) context.getRequest())                 .getRequestDispatcher("/j_spring_security_logout");         dispatcher.forward((ServletRequest) context.getRequest(),                (ServletResponse) context.getResponse());        FacesContext.getCurrentInstance().responseComplete();        // It's OK to return null here because Faces is just going to exit.        logger.debug("=================================================" +         ((HttpServletRequest)context.getRequest()).getSession().getId());               HttpSession session = ((HttpServletRequest)context.getRequest()).getSession();     //这是调整seam的集成部分    ContextControl.instance().begin(session);        return null;    }

jsf页面的做法
<t:inputText id="j_username" forceId="true" stylesize="20" value="#{loginBean.userName}"></t:inputText><t:inputSecret id="j_password" forceId="true" stylesize="20" value="#{loginBean.password}"<h:commandButton value="登录" action="#{loginBean.login}"></h:commandButton>


seam的集成:
因为在登录过程中,acegi注销掉了上一个session,创建了一个新的session,那么SeamListener这个session监听器就会执行sessionDestroyed和sessionCreated,但是seam并不认为你是真正销毁了所有的上下文包括request和application,我认为这是seam为了在页面过期的环境中使用,因为它的原则是由seam的Seam.invalidateSession()来处理session的销毁(事实上根本就没有销毁session而是给出了销毁的标记,也许这样就可以由它的内部解决所有上下文的管理)。那么就会产生异常,同样在这一次请求中seam的阶段监听也会产生异常,因为Conversation绑定的session仍然是已经过期的session。我的做法很傻,hack了!

一:自定义SeamListener
@Overridepublic void sessionCreated(HttpSessionEvent event) {// TODO Auto-generated method stubsuper.sessionCreated(event);}@Overridepublic void sessionDestroyed(HttpSessionEvent event) {// TODO Auto-generated method stub//event.getSession().getAttribute("org.jboss.seam.sessionInvalid");try {super.sessionDestroyed(event);} catch (IllegalStateException e) {// TODO: handle exceptionSeam.invalidateSession();HttpSession session = event.getSession();ContextControl.instance().end(session.getServletContext(), new ServletSessionImpl(session));}}


二 创建自定义的seam上下文控制类,直接操作各个上下文,对于session销毁和创建手动去清理或者创建其他各上下文实例。因为各个上下文的操作都是protect,所以只有将类建在它的包下了!
package org.jboss.seam.contexts;import java.util.Set;import javax.servlet.ServletContext;import javax.servlet.http.HttpSession;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.jboss.seam.Component;import org.jboss.seam.ScopeType;import org.jboss.seam.core.ConversationEntries;import org.jboss.seam.servlet.ServletSessionImpl;public class ContextControl {private static final Log log = LogFactory.getLog(ContextControl.class);private static final ContextControl contextControl = new ContextControl();public static ContextControl instance() {return contextControl;}public void begin(HttpSession session) {      boolean applicationContextActive = Contexts.isApplicationContextActive();      boolean eventContextActive = Contexts.isEventContextActive();      boolean conversationContextActive = Contexts.isConversationContextActive();      if ( !applicationContextActive )      {         Context tempApplicationContext = new WebApplicationContext(session.getServletContext());         Contexts.applicationContext.set(tempApplicationContext);      }      Context tempEventContext = null;      if ( !eventContextActive )      {         tempEventContext = new MapContext(ScopeType.EVENT);         Contexts.eventContext.set(tempEventContext);      }      Context tempConversationContext = null;      if ( !conversationContextActive )      {         tempConversationContext = new MapContext(ScopeType.CONVERSATION);         Contexts.conversationContext.set(tempConversationContext);      }      Context tempSessionContext = new WebSessionContext(new ServletSessionImpl(session));      Contexts.sessionContext.set(tempSessionContext);            //instantiate all session-scoped @Startup components      for ( String name : Contexts.getApplicationContext().getNames() )      {         Object object = Contexts.getApplicationContext().get(name);         if ( object!=null && (object instanceof Component) )          {            Component component = (Component) object;            if ( component.isStartup() && component.getScope() == ScopeType.SESSION )            {               startup(component);            }         }      }      }public void end(ServletContext servletContext, ContextAdaptor session) {            Context tempApplicationContext = new WebApplicationContext(servletContext);      Contexts.applicationContext.set(tempApplicationContext);      //this is used just as a place to stick the ConversationManager      Context tempEventContext = new MapContext(ScopeType.EVENT);      Contexts.eventContext.set(tempEventContext);      //this is used (a) for destroying session-scoped components      //and is also used (b) by the ConversationManager      Context tempSessionContext = new WebSessionContext(session);      Contexts.sessionContext.set(tempSessionContext);      Set<String> conversationIds = ConversationEntries.instance().getConversationIds();      log.debug("destroying conversation contexts: " + conversationIds);      for (String conversationId: conversationIds)      {         Lifecycle.destroyConversationContext(session, conversationId);      }            //we need some conversation-scope components for destroying      //the session context...      Context tempConversationContext = new MapContext(ScopeType.CONVERSATION);      Contexts.conversationContext.set(tempConversationContext);      log.debug("destroying session context");      Contexts.destroy(tempSessionContext);      Contexts.sessionContext.set(null);            Contexts.destroy(tempConversationContext);      Contexts.conversationContext.set(null);      Contexts.destroy(tempEventContext);      Contexts.eventContext.set(null);      Contexts.applicationContext.set(null);}   private static void startup(Component component)   {      if ( component.isStartup() )      {         for ( String dependency: component.getDependencies() )         {            Component dependentComponent = Component.forName(dependency);            if (dependentComponent!=null)            {               startup( dependentComponent );            }         }      }      if ( !component.getScope().getContext().isSet( component.getName() ) )       {         log.info("starting up: " + component.getName());         component.newInstance();      }   }}


这些只是我的做法!
注意的地方:
websphere 6.1.0.3以上版本默认对于找不到资源的url路径直接过滤到错误页面,这样spring的/j_spring_security_check是访问不到的,需要参考http://topic.csdn.net/u/20080620/14/9c05c7d7-a6a0-4646-95b2-4bdadcb1002c.html 1 楼 Dony 2009-01-08   最近正在整理以前的安全系统, 没有用过Spring Security, 但是想研究一下; 请教lz一个问题: Spring Security非得绑定Springframework吗? 2 楼 fangshun 2009-01-08   回复ls,一定的

热点排行