日历
网志分类
· 所有网志 (57)
· 技术 (21)
· 牢骚 (17)
· 未分类 (19)
站内搜索
友情链接
· 我的歪酷
· google
· developerworks
· MDA,UML,XML,Eclipse及Java相关的Blog
· 葛大姐
· 施大姐
· 陆小妹
· msg
· howImiss
· 第二书店
· http://www.csdn.net/
· http://www.itpub.net/
· 爬爬大陆漫画专区
· 唧唧歪歪在线漫画

订阅 RSS

0029523

歪酷博客

我是风,xiu~~~~


« 上一篇: 兴趣有点泛滥了...... 下一篇: 无题 »
xiuxiu @ 2007-11-29 00:26

其后我阅读了acegi的源代码, 得到以下结论:
1)Acegi通过HttpSessionContextIntergrationFilter在Session中保留认证信息,让不同的请求共享这些信息.
2)Acegi通过SecurityHolder在ThreadLocale(可选择Strategy)中保留认证信息,让一次请求的不同Filter共享这些信息.
最终,把目标锁定在了HttpSessionContextIntergrationFilter(我也真笨,人家这么明显的一个名字-,-).
水平不够,也就照抄了一下人家的源码,把session.setAtribute(),session.getAttribute()替换了.

/**
 *
 */
package com.xiuxiu.acegimemcached.cache;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import net.spy.memcached.MemcachedClient;

import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.context.SecurityContextImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

/**
 * @author Xiu
 *
 */
public class MemcachedContextIntegrationFilter implements InitializingBean,
        Filter {

    //~ Static fields/initializers =====================================================================================

    protected static final Log logger = LogFactory.getLog(HttpSessionContextIntegrationFilter.class);
    private static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied";
    public static final String ACEGI_SECURITY_CONTEXT_KEY = "ACEGI_SECURITY_CONTEXT";

    //~ Instance fields ================================================================================================

    private Class context = SecurityContextImpl.class;
    private Object contextObject;
    private static int EXP = 3000;   
    private MemcachedClient memcachedClient;

    /**
     * Indicates if this filter can create a <code>HttpSession</code> if needed (sessions are always created
     * sparingly, but setting this value to <code>false</code> will prohibit sessions from ever being created).
     * Defaults to <code>true</code>. Do not set to <code>false</code> if you are have set {@link
     * #forceEagerSessionCreation} to <code>true</code>, as the properties would be in conflict.
     */
    private boolean allowSessionCreation = true;

    /**
     * Indicates if this filter is required to create a <code>HttpSession</code> for every request before
     * proceeding through the filter chain, even if the <code>HttpSession</code> would not ordinarily have been
     * created. By default this is <code>false</code>, which is entirely appropriate for most circumstances as you do
     * not want a <code>HttpSession</code> created unless the filter actually needs one. It is envisaged the main
     * situation in which this property would be set to <code>true</code> is if using other filters that depend on a
     * <code>HttpSession</code> already existing, such as those which need to obtain a session ID. This is only
     * required in specialised cases, so leave it set to <code>false</code> unless you have an actual requirement and
     * are conscious of the session creation overhead.
     */
    private boolean forceEagerSessionCreation = false;
   
    /**
     * Indicates whether the <code>SecurityContext</code> will be cloned from the <code>HttpSession</code>. The
     * default is to simply reference (ie the default is <code>false</code>). The default may cause issues if
     * concurrent threads need to have a different security identity from other threads being concurrently processed
     * that share the same <code>HttpSession</code>. In most normal environments this does not represent an issue,
     * as changes to the security identity in one thread is allowed to affect the security identitiy in other
     * threads associated with the same <code>HttpSession</code>. For unusual cases where this is not permitted,
     * change this value to <code>true</code> and ensure the {@link #context} is set to a <code>SecurityContext</code>
     * that implements {@link Cloneable} and overrides the <code>clone()</code> method.
     */
    private boolean cloneFromHttpSession = false;

    public boolean isCloneFromHttpSession() {
        return cloneFromHttpSession;
    }

    public void setCloneFromHttpSession(boolean cloneFromHttpSession) {
        this.cloneFromHttpSession = cloneFromHttpSession;
    }

    public MemcachedContextIntegrationFilter() throws ServletException {
        this.contextObject = generateNewContext();
    }

    //~ Methods ========================================================================================================

    public void afterPropertiesSet() throws Exception {
        if ((this.context == null) || (!SecurityContext.class.isAssignableFrom(this.context))) {
            throw new IllegalArgumentException(
                "context must be defined and implement SecurityContext (typically use org.acegisecurity.context.SecurityContextImpl; existing class is "
                + this.context + ")");
        }

        if ((forceEagerSessionCreation == true) && (allowSessionCreation == false)) {
            throw new IllegalArgumentException(
                "If using forceEagerSessionCreation, you must set allowSessionCreation to also be true");
        }
    }

    /**
     * Does nothing. We use IoC container lifecycle services instead.
     */
    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        if ((request != null) && (request.getAttribute(FILTER_APPLIED) != null)) {
            // ensure that filter is only applied once per request
            chain.doFilter(request, response);
        } else {
            if (request != null) {
                request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
            }

            HttpSession httpSession = null;
            boolean httpSessionExistedAtStartOfRequest = false;

            try {
                httpSession = ((HttpServletRequest) request).getSession(forceEagerSessionCreation);
            } catch (IllegalStateException ignored) {}

            if (httpSession != null) {
                httpSessionExistedAtStartOfRequest = true;

                Object contextFromSessionObject = this.memcachedClient.get(String.valueOf(httpSession.getId()));
               
                // Clone if required (see SEC-356)
                if (cloneFromHttpSession) {
                    Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, "Context must implement Clonable and provide a Object.clone() method");
                    try {
                        Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[] {});
                        if (!m.isAccessible()) {
                            m.setAccessible(true);
                        }
                        contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[] {});
                    } catch (Exception ex) {
                        ReflectionUtils.handleReflectionException(ex);
                    }
                }
               
                if (contextFromSessionObject != null) {
                    if (contextFromSessionObject instanceof SecurityContext) {
                        if (logger.isDebugEnabled()) {
                            logger.debug(
                                "Obtained from ACEGI_SECURITY_CONTEXT a valid SecurityContext and set to SecurityContextHolder: '"
                                + contextFromSessionObject + "'");
                        }

                        SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);
                    } else {
                        if (logger.isWarnEnabled()) {
                            logger.warn("ACEGI_SECURITY_CONTEXT did not contain a SecurityContext but contained: '"
                                + contextFromSessionObject
                                + "'; are you improperly modifying the HttpSession directly (you should always use SecurityContextHolder) or using the HttpSession attribute reserved for this class? - new SecurityContext instance associated with SecurityContextHolder");
                        }

                        SecurityContextHolder.setContext(generateNewContext());
                    }
                } else {
                    if (logger.isDebugEnabled()) {
                        logger.debug(
                            "HttpSession returned null object for ACEGI_SECURITY_CONTEXT - new SecurityContext instance associated with SecurityContextHolder");
                    }

                    SecurityContextHolder.setContext(generateNewContext());
                }
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug(
                        "No HttpSession currently exists - new SecurityContext instance associated with SecurityContextHolder");
                }

                SecurityContextHolder.setContext(generateNewContext());
            }

            // Make the HttpSession null, as we want to ensure we don't keep
            // a reference to the HttpSession laying around in case the
            // chain.doFilter() invalidates it.
            httpSession = null;

            // Proceed with chain
            int contextWhenChainProceeded = SecurityContextHolder.getContext().hashCode();

            try {
                chain.doFilter(request, response);
            } catch (IOException ioe) {
                throw ioe;
            } catch (ServletException se) {
                throw se;
            } finally {
                // do clean up, even if there was an exception
                // Store context back to HttpSession
                try {
                    httpSession = ((HttpServletRequest) request).getSession(false);
                } catch (IllegalStateException ignored) {}

                if ((httpSession == null) && httpSessionExistedAtStartOfRequest) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(
                            "HttpSession is now null, but was not null at start of request; session was invalidated, so do not create a new session");
                    }
                }

                // Generate a HttpSession only if we need to
                if ((httpSession == null) && !httpSessionExistedAtStartOfRequest) {
                    if (!allowSessionCreation) {
                        if (logger.isDebugEnabled()) {
                            logger.debug(
                                "The HttpSession is currently null, and the HttpSessionContextIntegrationFilter is prohibited from creating a HttpSession (because the allowSessionCreation property is false) - SecurityContext thus not stored for next request");
                        }
                    } else if (!contextObject.equals(SecurityContextHolder.getContext())) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("HttpSession being created as SecurityContextHolder contents are non-default");
                        }

                        try {
                            httpSession = ((HttpServletRequest) request).getSession(true);
                        } catch (IllegalStateException ignored) {}
                    } else {
                        if (logger.isDebugEnabled()) {
                            logger.debug(
                                "HttpSession is null, but SecurityContextHolder has not changed from default: ' "
                                + SecurityContextHolder.getContext()
                                + "'; not creating HttpSession or storing SecurityContextHolder contents");
                        }
                    }
                }

                // If HttpSession exists, store current SecurityContextHolder
                // contents
                // but only if SecurityContext has actually changed (see JIRA
                // SEC-37)
                if ((httpSession != null)
                    && (SecurityContextHolder.getContext().hashCode() != contextWhenChainProceeded)) {
                    this.memcachedClient.set(httpSession.getId(), EXP , SecurityContextHolder.getContext());

                    if (logger.isDebugEnabled()) {
                        logger.debug("SecurityContext stored to HttpSession: '" + SecurityContextHolder.getContext()
                            + "'");
                    }
                }

                // Remove SecurityContextHolder contents
                SecurityContextHolder.clearContext();

                if (logger.isDebugEnabled()) {
                    logger.debug("SecurityContextHolder set to new context, as request processing completed");
                }
            }
        }
    }

    public SecurityContext generateNewContext() throws ServletException {
        try {
            return (SecurityContext) this.context.newInstance();
        } catch (InstantiationException ie) {
            throw new ServletException(ie);
        } catch (IllegalAccessException iae) {
            throw new ServletException(iae);
        }
    }

    public Class getContext() {
        return context;
    }

    /**
     * Does nothing. We use IoC container lifecycle services instead.
     *
     * @param filterConfig ignored
     *
     * @throws ServletException ignored
     */
    public void init(FilterConfig filterConfig) throws ServletException {}

    public boolean isAllowSessionCreation() {
        return allowSessionCreation;
    }

    public boolean isForceEagerSessionCreation() {
        return forceEagerSessionCreation;
    }

    public void setAllowSessionCreation(boolean allowSessionCreation) {
        this.allowSessionCreation = allowSessionCreation;
    }

    public void setContext(Class secureContext) {
        this.context = secureContext;
    }

    public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) {
        this.forceEagerSessionCreation = forceEagerSessionCreation;
    }

    /**
     * @return the memcachedClient
     */
    public MemcachedClient getMemcachedClient() {
        return memcachedClient;
    }

    /**
     * @param memcachedClient the memcachedClient to set
     */
    public void setMemcachedClient(MemcachedClient memcachedClient) {
        this.memcachedClient = memcachedClient;
    }
}

    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
        <property name="filterInvocationDefinitionSource">
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /**=memcachedContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
            </value>
        </property>
    </bean>

    <bean id="memcachedContextIntegrationFilter" class="com.xiuxiu.acegimemcached.cache.MemcachedContextIntegrationFilter">
                <property name="memcachedClient" ref="memcachedClient"/>
    </bean>

测试成功,ohyeah....

后记:对于(一)中提到的第二篇文章一直有一些误解.他是对用户-->角色,角色-->权限的信息进行扩展并且缓存,而不是对当前用户的信息进行缓存.一开始走了很多弯路.
5 performance test + concurrency test ( to be continued )
6 java client source code and memcached source code Reading ( to be continued )



最新评论


louis vuitton bags

2010-12-18 08:36 匿名 10.8.*.* 网址: http://www.louis-vuittons-outlet.com/

自我克制正是道德得以建立的基础。



dgdgdh

2012-03-07 15:39 匿名 126.19.*.*

Louis Vuitton impermeabile, leggenda del fuoco, la reale portata è difficile da rintracciare, [url=http://www.hoganscarpeuomo2012.com]hogan scarpe[/url] ma non usa pelle o altra pelle normale, invece di utilizzare un dipinto, chiamato Canvas, materiali tela,[url=http://www.louisvuittontaskedk.com]Louis Vuitton väska[/url] più uno strato di PVC impermeabile, anzi, il bene vecchia borsa, facile da indossare. Oltre al "durevole", cento e cinquanta anni di storia, Louis Vuitton, fin dall'inizio, specializzata nel mercato reale e aristocratica, [url=http://www.hoganscarpeuomo2012.com]hogan scarpe donna[/url] ma anche per il marchio di stare ferma ragione. Nel 1888, Louis Vuitton modello quadrato al posto del riso originale, strisce marroni, e insieme ai marchi registrati [url=http://www.louisvuittonsacsiteofficiel.com]sacs louis vuitton[/url]  di merci contraffatte è ancora pieno di tutto il mondo, di nuovo nel 1896, Louis Vuitton lettere, quattro a forma di fiore positivi e negativi diamond nuovo design schemi, che è l'origine Monogram famosi. Monogram questo modello, infatti,[url=http://www.louisvuittonsacsiteofficiel.com]louis vuitton sacs[/url]  dal XIX secolo, quando l'arte popolare orientale, sia per effetto decorativo e la pratica della pittura Nabis colpiti. I quattro diamanti a forma di fiore e di positivo e negativo sono l'essenza di entrambi fusione.[url=http://www.louisvuittontaskedk.com]Louis Vuitton taske[/url] Questo modello classico seguiti più di cento anni, quasi tutti gli amanti del Louis Vuitton la prima voce di pattern serie merci. L'integrazione di classico e moda Parla passato circa il discorso  [url=http://www.hoganscarpeuomo2012.com]hogan scarpe uomo[/url] classico Louis Vuitton per la tendenza degli ultimi anni, ha finalmente cambiato lo stile di. 1996, per celebrare il 100 ° anniversario della serie Monogram, invitare sette designer di moda lo stile edizione [url=http://www.louisvuittontaskedk.com/lv-mahina-leather]Louis Vuitton tasker[/url] limitata, innescato una pazza collezione di boom in tutto il mondo, così che Louis Vuitton comprendere la grandezza tendenza. 1998, Louis Vuitton, la prima volta di trovare designer americano MarcJacobs [url=http://www.louisvuittonsacsiteofficiel.com]louis vuitton site officiel [/url]  unito progettato serie Vernis, e anche allora lo sviluppo non ha mai avuto una linea di abbigliamento, oltre ai bagagli, pelletteria e della moda, disponibilità a cambiare secolare negozio Louis Vuitton farà un passo in altro campo della moda. Marc dagli [url=http://www.louisvuittontaskedk.com] Louis Vuitton[/url]  Stati Uniti, ma era profondamente affascinato dalla storia di abbigliamento, la cultura, le radici e lo spirito classico. Filosofia di design di Marc essere pratico, crede che la visione unica delle persone di moda per essere in grado [url=http://www.louisvuittontaskedk.com/lv-mahina-leather] Louis Vuitton taske[/url]  di usura è il più pratico, concentrandosi su design si fondono i dettagli della vita personale, deriva da uno stile superiore della femminilità.[url=http://www.louisvuittonsacsiteofficiel.com]louis vuitton [/url] Tronco Classic, borsa brillante e innovativo, nobile spirito Louis Vuitton e la qualità dello stesso, ma sapientemente vestita di Louis Vuitton Marc messo su una nuova espressione,  più vicino alla vita del pubblico.Artista giapponese Takashi Murakami (Takashi Myrakami) sovvertire il mondo dei cartoni animati, Louis Vuitton,la sovversione del mondo intero, Louis Vuitton modello monogramma incontrato varietà di colori fantastici per invertire l'impressione visiva del popolo. Leighton tempo, [url=http://www.hoganscarpeuomo2012.com]hogan scarpe 2012[/url]  fiori rider Takashi Murakami e segni di occhi, si trasformò in una varietà di forme ad apparire nei prodotti Louis Vuitton. Il marchio classico in Occidente ha incontrato l'artista orientale astratta, questo matrimonio di moda e arte è stato un successo enorme.[url=http://www.louisvuittonsacssiteofficiel.blogspot.com/]louis vuitton sacs [/url]
Takashi Murakami molto affascinato da Marc Jacobs ha detto di apprezzare di più è il lato oscuro del fondo delle opere gioia Murakami Takashi, ma ha anche la luce e le tenebre è la vita reale, e Marc Jacobs per guidare la Louis Vuitton in avanti [url=http://www.louisvuittonsacssiteofficiel.blogspot.com/]louis vuitton site officiel [/url]
[url=http://www.mbtzapatosspain.com]MBT zapatos[/url]  [url=http://www.zapatosoutlet2011.com]MBT zapatos[/url] [url=http://www.belstaffjacke2011.com/]belstaff[/url] [url=http://www.mbtzapatosspain.com]MBT outlet[/url]  [url=http://www.zapatosoutlet2011.com]MBT outlet[/url] [url=http://www.nikeskodmark.com]nike sko[/url] [url=http://www.barcelonacamisetas.org] camisetas de barcelona[/url] [url=http://www.barcelonacamisetas.org] nba camisetas[/url] [url=http://www.barcelonacamisetas.org] camiseta del Barcelona[/url] [url=http://www.barcelonacamisetas.org] camisetas del Barcelona[/url]


评论 / 个人网页 / 扔小纸条
*昵称

已经注册过? 请登录

Email
网址
*评论