NutzCN Logo
问答 实现PathMatchingFilter shiro的过滤器 如何在shiro之前执行呢
发布于 1834天前 作者 Hamming 6952 次浏览 复制 上一个帖子 下一个帖子
标签:

想定义过滤器 存储 shrio sesssion 信息
继承PathMatchingFilter 还需要实现 implements ActionFilter 方法吗

package io.nutz.nutzsite.common.shiro.filter;

import io.nutz.nutzsite.common.bean.OnlineSession;
import io.nutz.nutzsite.common.constant.ShiroConstants;
import io.nutz.nutzsite.common.shiro.session.OnlineSessionDAO;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 同步Session数据到Db
 *
 * @author ruoyi
 */
@IocBean
public class SyncOnlineSessionFilter extends PathMatchingFilter {
    @Inject
    private OnlineSessionDAO onlineSessionDAO;

    /**
     * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
     */
    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
        // 如果session stop了 也不同步
        // session停止时间,如果stopTimestamp不为null,则代表已停止
        if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) {
            onlineSessionDAO.syncToDb(session);
        }
        return true;
    }
}

25 回复

还是 实现 WebFilterFace 接口

这是要弄session持久化?

不是 可以记录在线人数 让它强制下线

酱紫 定义了 然后 启动 报错

package io.nutz.nutzsite.common.starter;

import io.nutz.nutzsite.common.bean.OnlineSession;
import io.nutz.nutzsite.common.constant.ShiroConstants;
import io.nutz.nutzsite.common.shiro.session.OnlineSessionDAO;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.nutz.boot.starter.WebFilterFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.EnumSet;
import java.util.Map;

/**
 * 同步Session数据到Db
 *
 * @author haimming
 */
@IocBean
public class SyncOnlineSessionFilter extends PathMatchingFilter implements WebFilterFace {
    @Inject("refer:$ioc")
    protected Ioc ioc;

    @Inject
    private OnlineSessionDAO onlineSessionDAO;

    @Override
    public String getName() {
        return "syncOnlineSession";
    }

    @Override
    public String getPathSpec() {
        return "/*";
    }
    /**
     * 需要支持哪些请求方式
     *
     * @return 请求方式列表
     */
    @Override
    public EnumSet<DispatcherType> getDispatches() {
        return EnumSet.of( DispatcherType.FORWARD,
                DispatcherType.INCLUDE,
                DispatcherType.REQUEST,
                DispatcherType.ASYNC,
                DispatcherType.ERROR);
    }

    @Override
    public Filter getFilter() {
        return ioc.get(SyncOnlineSessionFilter.class, "syncOnlineSessionFilter");
    }

    @Override
    public Map<String, String> getInitParameters() {
        return null;
    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
     */
    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
        // 如果session stop了 也不同步
        // session停止时间,如果stopTimestamp不为null,则代表已停止
        if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) {
            onlineSessionDAO.syncToDb(session);
        }
        return true;
    }
}

[DEBUG] 15:36:38.895 org.nutz.ioc.impl.ScopeContext.remove(ScopeContext.java:85) - Remove object 'syncOnlineSessionFilter' from [app] 
[WARN ] 15:36:38.895 org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:554) - Failed startup of context o.e.j.w.WebAppContext@2489e84a{/,[file:///Users/apple/IdeaProjects/ns/src/main/resources/static/, file:///Users/apple/IdeaProjects/ns/target/classes/static/, jar:file:/Users/apple/.m2/repository/org/nutz/nutzboot-starter-swagger/2.3.4.v20190410/nutzboot-starter-swagger-2.3.4.v20190410.jar!/static/],UNAVAILABLE}
org.nutz.ioc.IocException: IocBean[syncOnlineSessionFilter] throw Exception when creating
	at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:153)
	at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:241)
	at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:271)
	at org.nutz.boot.AppContext.getBeans(AppContext.java:334)
	at org.nutz.boot.starter.servlet3.NbServletContextListener.contextInitialized(NbServletContextListener.java:116)
	at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:957)
	at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:553)
	at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:922)
	at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:365)
	at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1497)
	at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1459)
	at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:852)
	at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:278)
	at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:138)
	at org.eclipse.jetty.server.Server.start(Server.java:415)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:108)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.server.Server.doStart(Server.java:382)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.nutz.boot.starter.jetty.JettyStarter.start(JettyStarter.java:137)
	at org.nutz.boot.AppContext.startServers(AppContext.java:310)
	at org.nutz.boot.NbApp.execute(NbApp.java:210)
	at org.nutz.boot.NbApp.run(NbApp.java:182)
	at io.nutz.nutzsite.MainLauncher.main(MainLauncher.java:66)
Caused by: java.lang.RuntimeException: IocBean[syncOnlineSessionFilter] fail at field=[onlineSessionDAO]
	at org.nutz.ioc.weaver.FieldInjector.inject(FieldInjector.java:40)
	at org.nutz.ioc.weaver.DefaultWeaver.fill(DefaultWeaver.java:67)
	at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:138)
	... 25 more
Caused by: org.nutz.ioc.IocException: IocBean[onlineSessionDAO] throw Exception when creating
	at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:153)
	at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:241)
	at org.nutz.ioc.val.ReferTypeValue.get(ReferTypeValue.java:60)
	at org.nutz.ioc.weaver.FieldInjector.inject(FieldInjector.java:32)
	... 27 more
Caused by: java.lang.RuntimeException: IocBean[onlineSessionDAO] fail at field=[onlineSessionFactory]
	at org.nutz.ioc.weaver.FieldInjector.inject(FieldInjector.java:40)
	at org.nutz.ioc.weaver.DefaultWeaver.fill(DefaultWeaver.java:67)
	at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:138)
	... 30 more
Caused by: org.nutz.ioc.IocException: IocBean[class:io.nutz.nutzsite.common.shiro.session.OnlineSessionFactory] none ioc bean match class=io.nutz.nutzsite.common.shiro.session.OnlineSessionFactory
	at org.nutz.ioc.impl.NutIoc.getByType(NutIoc.java:461)
	at org.nutz.ioc.val.ReferTypeValue.get(ReferTypeValue.java:66)
	at org.nutz.ioc.weaver.FieldInjector.inject(FieldInjector.java:32)
	... 32 more
[INFO ] 15:36:38.932 org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:292) - Started ServerConnector@7de15553{HTTP/1.1,[http/1.1]}{127.0.0.1:8090}
[INFO ] 15:36:38.932 org.eclipse.jetty.server.Server.doStart(Server.java:407) - Started @3700ms

你这是要把wk 重写一遍么……

不是 是参考 这个项目https://gitee.com/y_project/RuoYi
前端 做一个 nutz版本

none ioc bean match class=io.nutz.nutzsite.common.shiro.session.OnlineSessionFactory

MainLauncher在哪个package?

OnlineSessionFactory 没加iocbean吧

恩 果然是
现在错误变成这样
启动成功 没有执行方法onPreHandle

package io.nutz.nutzsite.common.starter;

import io.nutz.nutzsite.common.bean.OnlineSession;
import io.nutz.nutzsite.common.constant.ShiroConstants;
import io.nutz.nutzsite.common.shiro.session.OnlineSessionDAO;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.nutz.boot.starter.WebFilterFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

/**
 * 同步Session数据到Db
 *
 * @author haimming
 */
@IocBean(name = "syncOnlineSession")
public class SyncOnlineSessionFilter extends PathMatchingFilter implements WebFilterFace {
    @Inject("refer:$ioc")
    protected Ioc ioc;

    @Inject
    private OnlineSessionDAO onlineSessionDAO;

    @Override
    public String getName() {
        return "syncOnlineSession";
    }

    @Override
    public String getPathSpec() {
        return "/*";
    }
    /**
     * 需要支持哪些请求方式
     *
     * @return 请求方式列表
     */
    @Override
    public EnumSet<DispatcherType> getDispatches() {
        return EnumSet.of( DispatcherType.FORWARD,
                DispatcherType.INCLUDE,
                DispatcherType.REQUEST,
                DispatcherType.ASYNC,
                DispatcherType.ERROR);
    }

    @Override
    public Filter getFilter() {
        return ioc.get(SyncOnlineSessionFilter.class, "syncOnlineSession");
    }

    @Override
    public Map<String, String> getInitParameters() {
        return new HashMap<String, String>();
    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
     */
    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
        // 如果session stop了 也不同步
        // session停止时间,如果stopTimestamp不为null,则代表已停止
        if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) {
            onlineSessionDAO.syncToDb(session);
        }
        return true;
    }
}

为啥没有执行方法呢莫非是WebFilterFace不对

getFilter应该return this

至于为啥没有执行

要么order不对,没放在shiro之前

要么超类的逻辑问题,因为Filter接口就一个方法,你覆盖的是超类的方法,并非Filter的方法, web容器并不会直接调用到

定义 filter

package io.nutz.nutzsite.common.starter;

import io.nutz.nutzsite.common.filter.OnlineSessionFilter;
import org.nutz.boot.starter.WebFilterFace;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

/**
 * 同步Session数据到Db
 *
 * @author haimming
 */
@IocBean
public class SyncOnlineSessionFilter implements WebFilterFace {

    @Override
    public String getName() {
        return "syncOnlineSession";
    }

    @Override
    public String getPathSpec() {
        return "/*";
    }
    /**
     * 需要支持哪些请求方式
     *
     * @return 请求方式列表
     */
    @Override
    public EnumSet<DispatcherType> getDispatches() {
        return EnumSet.of( DispatcherType.FORWARD,
                DispatcherType.INCLUDE,
                DispatcherType.REQUEST,
                DispatcherType.ASYNC,
                DispatcherType.ERROR);
    }

    @Override
    public Filter getFilter() {
        return new OnlineSessionFilter();
    }

    @Override
    public Map<String, String> getInitParameters() {
        return new HashMap<String, String>();
    }

    @Override
    public int getOrder() {
        return 0;
    }


}

调用

package io.nutz.nutzsite.common.filter;

import io.nutz.nutzsite.common.bean.OnlineSession;
import io.nutz.nutzsite.common.constant.ShiroConstants;
import io.nutz.nutzsite.common.shiro.session.OnlineSessionDAO;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.mvc.ActionContext;
import org.nutz.mvc.ActionFilter;
import org.nutz.mvc.View;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * @Author: Haimming
 * @Date: 2019-04-19 09:38
 * @Version 1.0
 */
public class OnlineSessionFilter extends PathMatchingFilter  implements ActionFilter {

    @Inject
    private OnlineSessionDAO onlineSessionDAO;

    @Override
    public View match(ActionContext actionContext) {
        try {
            this.onPreHandle(actionContext.getRequest(),actionContext.getResponse(),actionContext.getMethodArgs());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
     */
    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
        // 如果session stop了 也不同步
        // session停止时间,如果stopTimestamp不为null,则代表已停止
        if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) {
            onlineSessionDAO.syncToDb(session);
        }
        return true;
    }
}

还是没有执行

WebFilterFace只能保证调用到Filter的doFilter方法, 其他方法是Filter实现类的事.

WebFilterFace的作用等同于web.xml里面声明个<filter><filter-mapping>

PS: 跟ActionFilter一点关系没有,实现ActionFilter没一点意义.

打断点 也没有执行 doFilter方法

package io.nutz.nutzsite.common.starter;

import io.nutz.nutzsite.common.bean.OnlineSession;
import io.nutz.nutzsite.common.constant.ShiroConstants;
import io.nutz.nutzsite.common.shiro.session.OnlineSessionDAO;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.nutz.boot.starter.WebFilterFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

/**
 * 同步Session数据到Db
 *
 * @author haimming
 */
@IocBean
public class SyncOnlineSessionFilter extends PathMatchingFilter implements WebFilterFace {
    @Inject("refer:$ioc")
    protected Ioc ioc;

    @Inject
    private OnlineSessionDAO onlineSessionDAO;

    @Override
    public String getName() {
        return "syncOnlineSession";
    }

    @Override
    public String getPathSpec() {
        return "/*";
    }
    /**
     * 需要支持哪些请求方式
     *
     * @return 请求方式列表
     */
    @Override
    public EnumSet<DispatcherType> getDispatches() {
        return EnumSet.of( DispatcherType.FORWARD,
                DispatcherType.INCLUDE,
                DispatcherType.REQUEST,
                DispatcherType.ASYNC,
                DispatcherType.ERROR);
    }

    @Override
    public Filter getFilter() {
        return this;
    }

    @Override
    public Map<String, String> getInitParameters() {
        return new HashMap<String, String>();
    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
     */
    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
        // 如果session stop了 也不同步
        // session停止时间,如果stopTimestamp不为null,则代表已停止
        if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) {
            onlineSessionDAO.syncToDb(session);
        }
        return true;
    }

    public void doFilter(){
        System.out.println(1);
    }
}

    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException;
Error:(84, 23) java: io.nutz.nutzsite.common.starter.SyncOnlineSessionFilter中的doFilter(javax.servlet.ServletRequest,javax.servlet.ServletResponse,javax.servlet.FilterChain)无法覆盖org.apache.shiro.web.servlet.OncePerRequestFilter中的doFilter(javax.servlet.ServletRequest,javax.servlet.ServletResponse,javax.servlet.FilterChain)
  被覆盖的方法为final

不是覆盖它,是debug它

你写个无参数的doFilter,又怎么可能被调用

PS: getOrder返回的值会影响filter的先后顺序

会执行doFilter看来是我继承的方法 不对

应该会比shiro 先执行

    @Override
    public int getOrder() {
        return 0;
    }

spring 这样配置 nutzboot如何在启动 时设置ShiroFilterFactoryBean.setFilter呢

  /**
     * Shiro过滤器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 身份认证失败,则跳转到登录页面的配置
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 权限认证失败,则跳转到指定页面
        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
        // Shiro连接约束配置,即过滤链的定义
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 对静态资源设置匿名访问
        filterChainDefinitionMap.put("/favicon.ico**", "anon");
        filterChainDefinitionMap.put("/ruoyi.png**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/docs/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/ajax/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/ruoyi/**", "anon");
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
        // 退出 logout地址,shiro去清除session
        filterChainDefinitionMap.put("/logout", "logout");
        // 不需要拦截的访问
        filterChainDefinitionMap.put("/login", "anon,captchaValidate");
        // 系统权限列表
        // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());

        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("onlineSession", onlineSessionFilter());
        filters.put("syncOnlineSession", syncOnlineSessionFilter());
        filters.put("captchaValidate", captchaValidateFilter());
        // 注销成功,则跳转到指定页面
        filters.put("logout", logoutFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 所有请求需要认证
        filterChainDefinitionMap.put("/**", "user,onlineSession,syncOnlineSession");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    /**
     * 自定义在线用户处理过滤器
     */
    @Bean
    public OnlineSessionFilter onlineSessionFilter()
    {
        OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
        onlineSessionFilter.setLoginUrl(loginUrl);
        return onlineSessionFilter;
    }

    /**
     * 自定义在线用户同步过滤器
     */
    @Bean
    public SyncOnlineSessionFilter syncOnlineSessionFilter()
    {
        SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
        return syncOnlineSessionFilter;
    }

研究出来了
可以酱紫玩
所有请求都会执行syncOnlineSessionFilter过滤器

##shiro
shiro.objects = syncOnlineSessionFilter
shiro.url.login=/login
shiro.url.unauth=/login/unauth
shiro.ini.urls:
/static/** = anon
/login = anon
/sys/** = authc
/index = authc
/druid/** =authc
/swagger/** =authc
/** =syncOnlineSessionFilter

添加回复
请先登陆
回到顶部