|
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" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
- <property name="cache"><ref local="userCacheBackend"/></property>
- </bean>
-
- <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
- <property name="cacheManager"> <ref local="cacheManager"/> </property>
- <property name="cacheName"> <value>userCache</value> </property>
- </bean>
-
- <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
-
- <!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
- <bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener" />
-
- <!-- <bean id="customAuthenticationFilter" class="**.authorization.CustomAuthenticationFilter">
- <security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
- </bean> 使用自定义的过滤器,参考spring security中不同的自定义位置名称-->
-
- </beans>
复制代码
jsf集成:
jsf跳转机制使用的是redirect,所以登录的信息就不能很好的传递给acegi,根据myfaces wiki提供的方式:创建登录使用的loginBean,注意不要使用seam的@Name注册为seam组件,直接使用jsf的managed-bean机制注册成backingbean
- 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页面的做法
[code="xml"]<t:inputText id="j_username" forceId="true" styleClass="form1" size="20" value="#{loginBean.userName}"></t:inputText>
<t:inputSecret id="j_password" forceId="true" styleClass="form1" size="20" value="#{loginBean.password}"
<h:commandButton value="登录" action="#{loginBean.login}"></h:commandButton>[/code]
seam的集成:
因为在登录过程中,acegi注销掉了上一个session,创建了一个新的session,那么SeamListener这个session***就会执行sessionDestroyed和sessionCreated,但是seam并不认为你是真正销毁了所有的上下文包括request和application,我认为这是seam为了在页面过期的环境中使用,因为它的原则是由seam的Seam.invalidateSession()来处理session的销毁(事实上根本就没有销毁session而是给出了销毁的标记,也许这样就可以由它的内部解决所有上下文的管理)。那么就会产生异常,同样在这一次请求中seam的阶段监听也会产生异常,因为Conversation绑定的session仍然是已经过期的session。我的做法很傻,hack了!
一:自定义SeamListener
- @Override
- public void sessionCreated(HttpSessionEvent event) {
- // TODO Auto-generated method stub
- super.sessionCreated(event);
- }
-
- @Override
- public 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 exception
- Seam.invalidateSession();
- HttpSession session = event.getSession();
- ContextControl.instance().end(session.getServletContext(), new ServletSessionImpl(session));
- }
- }
复制代码
二 创建自定义的seam上下文控制类,直接操作各个上下文,对于session销毁和创建手动去清理或者创建其他各上下文实例。因为各个上下文的操作都是protect,所以只有将类建在它的包下了!
这些只是我的做法!
注意的地方:
websphere 6.1.0.3以上版本默认对于找不到资源的url路径直接过滤到错误页面,这样spring的/j_spring_security_check是访问不到的,需要参考http://topic.csdn.net/u/20080620 ... 2-4bdadcb1002c.html |
|