shiro执行多个过滤器_实现PathMatchingFilter shiro的过滤器 如何在shiro之前执行呢

本文档讨论了在NutzBoot应用中,如何配置Shiro过滤器并确保自定义的`SyncOnlineSessionFilter`在Shiro过滤器之前执行,以实现Session数据到数据库的同步。作者遇到的问题包括IocBean创建异常、过滤器执行顺序不正确以及如何在ShiroFilterFactoryBean中设置自定义过滤器。通过调整过滤器的`getOrder()`方法和使用`WebFilterFace`接口,最终解决了问题。
摘要由CSDN通过智能技术生成

25 回复

这是要弄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 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 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

不是 是参考 这个项目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 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 getInitParameters() {

return new HashMap();

}

@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 getDispatches() {

return EnumSet.of( DispatcherType.FORWARD,

DispatcherType.INCLUDE,

DispatcherType.REQUEST,

DispatcherType.ASYNC,

DispatcherType.ERROR);

}

@Override

public Filter getFilter() {

return new OnlineSessionFilter();

}

@Override

public Map getInitParameters() {

return new HashMap();

}

@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里面声明个和

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 getDispatches() {

return EnumSet.of( DispatcherType.FORWARD,

DispatcherType.INCLUDE,

DispatcherType.REQUEST,

DispatcherType.ASYNC,

DispatcherType.ERROR);

}

@Override

public Filter getFilter() {

return this;

}

@Override

public Map getInitParameters() {

return new HashMap();

}

@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

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

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

应该会比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 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 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值