【问题标题】:custom shiro filter for rest api用于 rest api 的自定义 shiro 过滤器
【发布时间】:2022-12-11 11:52:04
【问题描述】:

我有一个旧的休息过滤器。下面可以移植到shiro.ini吗?或者,是否可以在 shiro.ini 中初始化/配置过滤器并使用 doFilter() 在 java 中扩展它?看起来错误处理和“shiro 错误”发生了一些奇怪的事情。我不是在找人来写我的代码,但提示在哪里寻找会有所帮助。谢谢你。

更新:MyRestFilter 类:

@Override
    @SneakyThrows(Throwable.class)
    public void doFilter(final HttpServletRequest request, final HttpServletResponse response, 
            HttpSession httpSession, final FilterChain chain) throws ServletException, IOException
    {
        debugRequest(request);
        List<String> sessionIds = Servlets.getRequestQueryStringMap(request).get(SESSION_ID);
        String sessionId = sessionIds == null? null : Iterables.getOnlyElement(sessionIds);
        String sessionIdHeader = request.getHeader(SESSION_ID_HEADER);
        if(sessionId == null)
        {
            sessionId = sessionIdHeader;
        }
        ThreadContext.unbindSubject();
        ThreadContext.bind(securityManager);
        if(sessionId != null)
        {
            // strip out host / instance ID from the session
            sessionId = sessionId.replaceFirst("\\.[\\w_\\-+]+$", "");
            Subject subject = new Subject.Builder().sessionId(sessionId).buildSubject();
            Session session = subject.getSession(false);
            if(session != null)
            {
                session.touch();   // this should not be necessary, but due to Shiro bug, it is
                StatefulUtil.pingStateful(session);
            }
            if(subject.getPrincipal() == null)
            {
                response.sendError(HttpStatus.SC_UNAUTHORIZED, "Unauthorized API Call");
            }
            else
            {
                try
                {
                    subject.execute(() ->
                    {
                        SharedWebstats webStats = Beans.getReference(SharedWebstats.class);
                        webStats.webStats("mobile");

                        if (chain != null)
                        {
                            chain.doFilter(request, response);
                        }
                        return null;
                    });
                }
                catch(ExecutionException e)
                {
                    // unwrap Shiro's ExecutionException, interferes
                    // with global exceptino handling mechanisms
                    Throwable cause = e.getCause();
                    if (cause != null)
                    {
                        throw cause;
                    } 
                    else
                    {
                        throw e;
                    }
                }
            }
        }
        else
        {            
            chain.doFilter(request, response);
        }
        ThreadContext.unbindSecurityManager();
    }

//MyRestFilter also contains an init() which contains the real problem: how to set a session timeout that applies to the /api/ url only? (note, many of these SecurityManagerFactories are deprecated which is why I have to rewrite this).

@Override
    public void init() throws ServletException
    {
        
        //securityManager = new WebIniSecurityManagerFactory("classpath:META-INF/shiro.ini").createInstance();
        securityManager = WebIniSecurityManagerFactory("classpath:META-INF/shiro.ini").createInstance();
        int sessionTimeout = WebXml.INSTANCE.getSessionTimeout();
        DefaultSecurityManager dsm = (DefaultSecurityManager)securityManager;
        DefaultSessionManager sm = (DefaultSessionManager)dsm.getSessionManager();
        sm.setGlobalSessionTimeout(sessionTimeout * 60 * 1000);
        realmCache.putAll(securityManager);
        ssse.addSessionListeners(sm.getSessionListeners());
    }
                
    private org.apache.shiro.mgt.SecurityManager securityManager;
    private @Inject RealmCacheHolder realmCache;
    private @Inject ShiroSessionScopeExtension ssse;

这是一些配置。目前我有:

<filter>
        <filter-name>ShiroFilter</filter-name>
        <filter-class>com.dependencyfromhell.shiro.ee.filters.ShiroFilter</filter-class>
        <async-supported>true</async-supported>
    </filter>
    <context-param>
        <param-name>shiroConfigLocations</param-name>
        <param-value>classpath:META-INF/shiro.ini</param-value>
    </context-param>
        
    <!-- Security - Enforce Filter Ordering -->
    <filter-mapping>
        <filter-name>ShiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher> 
        <dispatcher>FORWARD</dispatcher> 
        <dispatcher>INCLUDE</dispatcher> 
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>MyRestFilter</filter-name>
        <url-pattern/>
    </filter-mapping>

我想要这样的东西。

# rest support
rest = MyRestFilter

#Rest api
/api/* = MyRestFilter

我可以在 shiro.ini 中为会话超时配置 MyRestFilter,然后有一个带有 doFilter 方法的 MyRestFilter 类吗?谢谢。

【问题讨论】:

  • 乍一看,我会说是的,它可以转换为 Shiro 的配置。大多数逻辑由ShiroFilter 自动为您处理,此过滤器可能未正确设置或未在您的 servlet 之前得到处理。也就是说,我猜是有原因让你走上这条路的。您目前如何配置 Shiro?也许创建一个简单的独立示例? (用日志语句或其他内容替换您的Beans.getRefernce()
  • 我继承了一个代码噩梦哈哈。不过,我正在努力跟上 shiro 的步伐。更新了一些配置。如果我能提供其他任何东西,请告诉我。谢谢你。

标签: rest filter shiro


【解决方案1】:

您的 init() 方法看起来是问题的根源。

基本上配置了两个 Shiro 实例。一个来自 web.xml 中的 ShiroFilter,另一个来自自定义过滤器的 init() 方法。

我猜这是注入你的RealmCacheHolderShiroSessionScopeExtension 的解决方法,但不清楚它们是如何使用的。

您可以使用 IoC 框架引导 Shiro。 (Shiro 直接支持 Guice 和 Spring),如果您使用 CDI(或其他东西),它仍然可以完成,但它需要一些自定义代码(可能与您拥有的代码类似)。

您将实现 WebEnvironment 并使用其类名设置 shiroEnvironmentClass 过滤器上下文参数。

如果想更深入地了解 WebEnvironment 选项,您可能需要点击 Shiro User list

【讨论】:

    猜你喜欢
    • 2020-02-08
    • 1970-01-01
    • 2019-01-04
    • 2019-09-17
    • 2014-06-17
    • 2015-01-23
    • 1970-01-01
    • 2020-12-23
    • 2013-05-24
    相关资源
    最近更新 更多