每个账户同时只能有一个人登录或几个人同时登录,如果同时有多人登录:要么不让后者登录;要么踢出前者登录(强制退出),nutzbook如何实现?
基本思路如下:
// 不允许后者登录
Long re = jedis().setnx("u:sid:"+uid, sessionid);
if (re == 0) {
// 老session id存在, 检查一下是否过期. 如果没过期, 拒绝登录
}
shiro.login(...);
String oldSessionId = jedis().getSet("u:sid:"+uid, sessionid);
if (oldSessionId != null) {
// 老session id存在, 取出session, 注销掉
}
shiro.login(...);
@binfoo 是shiro还是http session哦
@At
public Object login(@Param("username") String username, @Param("password") String password,
@Param("captcha") String captcha,
@Attr(scope = Scope.SESSION, value = "nutz_captcha") String _captcha,
HttpSession session) {
NutMap re = new NutMap();
if (!Toolkit.checkCaptcha(_captcha, captcha)) {
return re.setv("ok", false).setv("msg", "验证码错误");
}
int userId = userService.fetch(username, password);
if (userId < 0) {
return re.setv("ok", false).setv("msg", "用户名或密码错误");
} else {
// Long usid = jedis().setnx("u:sid:"+userId, session.getId());
String key = "u:sid:" + userId;
jedisAgent.getResource().zadd(key, System.currentTimeMillis(), session.getId());//加入
Long size = jedisAgent.getResource().zcard(key);//求个数
log.info("session.size: " + size);
if (size > MAX_USER_ONLINE) {
jedisAgent.getResource().zrange(key, 0, 100);//zrange(key, start, end):返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素
String deleteMember = jedisAgent.getResource().mget(key).get(0);
log.info("sessionid :" + deleteMember);
//销毁老的
session.getSessionContext().getSession(deleteMember).invalidate();
jedisAgent.getResource().zremrangeByRank(key, 0, 1);//删掉第一个
}
session.setAttribute("me", userId);
// 完成nutdao_realm后启用.
SecurityUtils.getSubject().login(new SimpleShiroToken(userId));
return re.setv("ok", true);
}
}
@binfoo 那就是shiro session咯,SecurityUtils类有方法
@SessionBy(ShiroSessionProvider.class)
这个是MainModule里面的,应该是自定义的shiro session
public Object login(@Param("username") String username, @Param("password") String password,
@Param("captcha") String captcha,
@Attr(scope = Scope.SESSION, value = "nutz_captcha") String _captcha,
HttpSession session)
这个入参数是HttpSession,我想要shrio的缓存session,并且能够进行增删操作
实现新登陆的踢出老用户,取出来老的session然后注销,我的代码应该是不对的,求指教,对shiro不熟悉
Redis GETSET命令在Redis键中设置指定的字符串值,并返回其旧值。
//
// 返回值
//
// 返回一个字符串,也就是键的旧值。 如果键不存在,则返回nil。
final String oldSessinId = jedisPool.getResource().getSet("u:sid:" + userId, session.getId());
//取出来老的sessionId,然后注销掉,新登陆的踢掉老的用户
if (oldSessinId != null) {
Session sessionOld = SecurityUtils.getSecurityManager().getSession(new SessionKey() {
@Override
public Serializable getSessionId() {
return oldSessinId;
}
});
SecurityUtils.getSecurityManager().logout(subject);
}
// 完成nutdao_realm后启用.
subject.login(new SimpleShiroToken(userId));
// subject.getSession().setAttribute("me", userId);
return re.setv("ok", true);
}
日志报错
3c3e919c6cec
2017-04-10 17:18:07,561 org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:447) DEBUG - Resolved SubjectContext context session is invalid. Ignoring and creating an anonymous (session-less) Subject instance.
org.apache.shiro.session.UnknownSessionException: There is no session with id [9216e0fe-75a0-47ec-a04c-3c3e919c6cec]
at org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:170)
at org.apache.shiro.session.mgt.eis.CachingSessionDAO.readSession(CachingSessionDAO.java:261)
at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSessionFromDataSource(DefaultSessionManager.java:236)
at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSession(DefaultSessionManager.java:222)
at org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doGetSession(AbstractValidatingSessionManager.java:118)
at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupSession(AbstractNativeSessionManager.java:148)
at org.apache.shiro.session.mgt.AbstractNativeSessionManager.getSession(AbstractNativeSessionManager.java:140)
at org.apache.shiro.mgt.SessionsSecurityManager.getSession(SessionsSecurityManager.java:156)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveContextSession(DefaultSecurityManager.java:456)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:442)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:338)
at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:846)
at com.binfoo.www.module.UserModule.login(UserModule.java:97)
at com.binfoo.www.module.UserModule$$NUTZAOP._aop_invoke(UserModule.java:2)
at org.nutz.aop.InterceptorChain.invoke(InterceptorChain.java:77)
at org.nutz.aop.InterceptorChain.doChain(InterceptorChain.java:57)
at org.nutz.integration.jedis.RedisInterceptor.filter(RedisInterceptor.java:24)
at org.nutz.aop.InterceptorChain.doChain(InterceptorChain.java:60)
at com.binfoo.www.module.UserModule$$NUTZAOP.login(UserModule.java:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:25)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.integration.shiro.NutShiroProcessor.process(NutShiroProcessor.java:126)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:22)
at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:198)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
2017-04-10 17:18:07,564 org.apache.shiro.web.mgt.CookieRememberMeManager.getRememberedSerializedIdentity(CookieRememberMeManager.java:192) DEBUG - SubjectContext argument is not an HTTP-aware instance. This is required to obtain a servlet request and response in order to retrieve the rememberMe cookie. Returning immediately and ignoring rememberMe operation.
2017-04-10 17:18:07,564 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:151) DEBUG - Get 'dao'<interface org.nutz.dao.Dao>
2017-04-10 17:18:07,565 org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:147) DEBUG - sql = SELECT * FROM t_user WHERE id=?, tables = [t_user]
2017-04-10 17:18:07,565 org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:177) DEBUG - not good for cache >> SELECT * FROM t_user WHERE id=?
2017-04-10 17:18:07,565 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) DEBUG - SELECT * FROM t_user WHERE id=?
| 1 |
|---|
| 1 |
For example:> "SELECT * FROM t_user WHERE id=1"
2017-04-10 17:18:07,571 org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:569) DEBUG - Looked up AuthenticationInfo [1] from doGetAuthenticationInfo
2017-04-10 17:18:07,572 org.apache.shiro.realm.AuthenticatingRealm.cacheAuthenticationInfoIfPossible(AuthenticatingRealm.java:507) DEBUG - AuthenticationInfo caching is disabled for info [1]. Submitted token: [org.nutz.integration.shiro.SimpleShiroToken@5bbd0f27].
2017-04-10 17:18:07,572 org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:233) DEBUG - Authentication successful for token [org.nutz.integration.shiro.SimpleShiroToken@5bbd0f27]. Returned account [1]
2017-04-10 17:18:07,572 org.apache.shiro.subject.support.DefaultSubjectContext.resolveSecurityManager(DefaultSubjectContext.java:102) DEBUG - No SecurityManager available in subject context map. Falling back to SecurityUtils.getSecurityManager() lookup.
2017-04-10 17:18:07,572 org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:436) DEBUG - Context already contains a session. Returning.
2017-04-10 17:18:07,572 org.apache.shiro.subject.support.DefaultSubjectContext.resolveSecurityManager(DefaultSubjectContext.java:102) DEBUG - No SecurityManager available in subject context map. Falling back to SecurityUtils.getSecurityManager() lookup.
2017-04-10 17:18:07,572 org.apache.shiro.web.servlet.SimpleCookie.addCookieHeader(SimpleCookie.java:226) DEBUG - Added HttpServletResponse Cookie [rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Sun, 09-Apr-2017 09:18:07 GMT]
2017-04-10 17:18:07,573 org.apache.shiro.mgt.AbstractRememberMeManager.onSuccessfulLogin(AbstractRememberMeManager.java:290) DEBUG - AuthenticationToken did not indicate RememberMe is requested. RememberMe functionality will not be executed for corresponding account.
2017-04-10 17:18:07,574 com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:27) DEBUG - [POST]URI=/sysuser/login 46ms
2017-04-10 17:18:08,654 org.apache.shiro.web.servlet.SimpleCookie.readValue(SimpleCookie.java:389) DEBUG - Found 'JSESSIONID' cookie value [2b2ae48e-7e5d-4389-aab6-a81f6342bee5]
2017-04-10 17:18:08,654 org.nutz.mvc.impl.UrlMappingImpl.get(UrlMappingImpl.java:101) DEBUG - Found mapping for [GET] path=/sysuser/login : UserModule.loginPage(UserModule.java:203)
2017-04-10 17:18:08,655 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:151) DEBUG - Get 'userModule'<class com.binfoo.www.module.UserModule>
2017-04-10 17:18:08,799 com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:27) DEBUG - [ GET]URI=/sysuser/login 144ms
2017-04-10 17:18:08,821 org.apache.shiro.web.servlet.SimpleCookie.readValue(SimpleCookie.java:389) DEBUG - Found 'JSESSIONID' cookie value [2b2ae48e-7e5d-4389-aab6-a81f6342bee5]
2017-04-10 17:18:08,822 org.nutz.mvc.impl.UrlMappingImpl.get(UrlMappingImpl.java:101) DEBUG - Found mapping for [GET] path=/captcha/next : CaptchaModule.next(CaptchaModule.java:26)
2017-04-10 17:18:08,823 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:151) DEBUG - Get 'captchaModule'<class com.binfoo.www.module.CaptchaModule>
2017-04-10 17:18:08,850 com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:27) DEBUG - [ GET]URI=/captcha/next 28ms
2017-04-10 17:18:29,365 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
2017-04-10 17:18:52,779 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
2017-04-10 17:19:22,300 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
2017-04-10 17:19:49,337 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 1 triggers
2017-04-10 17:20:00,001 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:151) DEBUG - Get 'cleanNonActiveUserJob'<class com.binfoo.www.quartz.job.CleanNonActiveUserJob>
2017-04-10 17:20:00,001 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
2017-04-10 17:20:00,002 org.quartz.core.JobRunShell.run(JobRunShell.java:201) DEBUG - Calling execute on job DEFAULT.com.binfoo.www.quartz.job.CleanNonActiveUserJob
2017-04-10 17:20:00,002 com.binfoo.www.quartz.job.CleanNonActiveUserJob.execute(CleanNonActiveUserJob.java:31) DEBUG - clean Non-Active User , start
2017-04-10 17:20:00,003 org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:147) DEBUG - sql = DELETE FROM t_user_profile WHERE uid>? AND ct<? AND (email_checked=? OR email IS NULL ), tables = [t_user_profile]
2017-04-10 17:20:00,004 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) DEBUG - DELETE FROM t_user_profile WHERE uid>? AND ct<? AND (email_checked=? OR email IS NULL )
| 1 | 2 | 3 |
|----|---------------------|-------|
| 10 | 2017-04-09 17:20:00 | false |
For example:> "DELETE FROM t_user_profile WHERE uid>10 AND ct<'2017-04-09 17:20:00' AND (email_checked=false OR email IS NULL )"
2017-04-10 17:20:00,006 org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:194) DEBUG - Clear Cache=t_user_profile
2017-04-10 17:20:00,006 com.binfoo.www.quartz.job.CleanNonActiveUserJob.execute(CleanNonActiveUserJob.java:35) DEBUG - delete 0 UserProfile
2017-04-10 17:20:00,006 org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:147) DEBUG - sql = delete from t_user where id > 10 and not exists (select 1 from t_user_profile where t_user.id = uid ) and ct < ?, tables = [t_user, t_user_profile]
2017-04-10 17:20:00,007 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) DEBUG - delete from t_user where id > 10 and not exists (select 1 from t_user_profile where t_user.id = uid ) and ct < ?
| 1 |
|---------------------|
| 2017-04-09 17:20:00 |
For example:> "delete from t_user where id > 10 and not exists (select 1 from t_user_profile where t_user.id = uid ) and ct < '2017-04-09 17:20:00'"
2017-04-10 17:20:00,009 org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:194) DEBUG - Clear Cache=t_user
2017-04-10 17:20:00,009 org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:194) DEBUG - Clear Cache=t_user_profile
2017-04-10 17:20:00,009 com.binfoo.www.quartz.job.CleanNonActiveUserJob.execute(CleanNonActiveUserJob.java:42) DEBUG - delete 0 User
2017-04-10 17:20:00,009 com.binfoo.www.quartz.job.CleanNonActiveUserJob.execute(CleanNonActiveUserJob.java:44) DEBUG - clean Non-Active User , Done
2017-04-10 17:20:25,397 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
2017-04-10 17:20:50,081 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
2017-04-10 17:20:56,026 org.apache.shiro.web.servlet.SimpleCookie.readValue(SimpleCookie.java:389) DEBUG - Found 'JSESSIONID' cookie value [ba393b70-c084-4215-83d0-ddc8ad3757a0]
2017-04-10 17:20:56,026 org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:447) DEBUG - Resolved SubjectContext context session is invalid. Ignoring and creating an anonymous (session-less) Subject instance.
org.apache.shiro.session.UnknownSessionException: There is no session with id [ba393b70-c084-4215-83d0-ddc8ad3757a0]
at org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:170)
at org.apache.shiro.session.mgt.eis.CachingSessionDAO.readSession(CachingSessionDAO.java:261)
at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSessionFromDataSource(DefaultSessionManager.java:236)
at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSession(DefaultSessionManager.java:222)
at org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doGetSession(AbstractValidatingSessionManager.java:118)
at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupSession(AbstractNativeSessionManager.java:148)
at org.apache.shiro.session.mgt.AbstractNativeSessionManager.getSession(AbstractNativeSessionManager.java:140)
at org.apache.shiro.mgt.SessionsSecurityManager.getSession(SessionsSecurityManager.java:156)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveContextSession(DefaultSecurityManager.java:456)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:442)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:338)
at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:846)
at org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:148)
at org.apache.shiro.web.servlet.AbstractShiroFilter.createSubject(AbstractShiroFilter.java:292)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:359)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
具体登陆方法代码
@At
@Aop("redis")
public Object login(@Param("username") String username, @Param("password") String password,
@Param("captcha") String captcha,
@Attr(scope = Scope.SESSION, value = "nutz_captcha") String _captcha, HttpSession session
) {
NutMap re = new NutMap();
if (!Toolkit.checkCaptcha(_captcha, captcha)) {
return re.setv("ok", false).setv("msg", "验证码错误");
}
int userId = userService.fetch(username, password);
if (userId < 0) {
return re.setv("ok", false).setv("msg", "用户名或密码错误");
} else {
// Redis GETSET命令在Redis键中设置指定的字符串值,并返回其旧值。
//
// 返回值
//
// 返回一个字符串,也就是键的旧值。 如果键不存在,则返回nil。
String oldSessionId = jedis().getSet("u:sid:" + userId, session.getId());
System.out.println("sessionId = " + session.getId() + "and oldSessionId = " + oldSessionId);
if (oldSessionId != null && oldSessionId != session.getId()) {
//取出来老的sessionId,然后注销掉,新登陆的踢掉老的用户
new Subject.Builder().sessionId(oldSessionId).buildSubject().logout();
}
// 完成nutdao_realm后启用.
SecurityUtils.getSubject().login(new SimpleShiroToken(userId));
//当前用户登录
// subject.getSession().setAttribute("me", userId);
return re.setv("ok", true);
}
}
try catch一下嘛 , 老session 已经过期的话, 自然会抛错.
try {
new Subject.Builder().sessionId(oldSessionId).buildSubject().logout();
} catch (Exception) {}
哎,我发现没有用,我是用的nutzbook教程练习的,集成了shiro的权限,貌似shiro 的session是缓存在ehcache里面的,这样我把session又缓存到redis,使用new Subject.Builder().sessionId(oldSessionId).buildSubject().logout();这个踢出去,实际上没啥用。。。
就是我用360浏览器登录,然后进行查看用户列表,同时我用ie浏览器继续登陆,如果正确的话,360的应该被踢出,可实际上360浏览器还是可以继续工作。。。
哎
分步排查嘛:
首先, A浏览器登录, 得到session id, 检查redis内的值是否正确
然后, B浏览器登录, login方法开debug或者打印日志, 观察B浏览器的session id, 及redis中读取到的老session id
如果老session id, 也就是A浏览器的id被正确读取出来, 那就是要看 "new Subject.Builder().sessionId(oldSessionId)" 是否正常的, 因为能拿到session 才能logout
我设计了一个测试方法, 用于验证: 根据一个session id, 将其所属的session注销掉
@Filters
@At
@Ok("raw")
public String seid(HttpSession session) {
return session.getId() + "," + SecurityUtils.getSubject().isAuthenticated();
}
@Filters
@At("/logout/?")
@Ok("http:200")
public void logoutBySeid(String seid) {
new Subject.Builder().sessionId(seid).buildSubject().logout();
}
浏览器分别是 Chrome 和 Firefox的最新版, 他们肯定不会共享cookie了
然后, 使用Chrome浏览器进行登录, 完成后访问
http://127.0.0.1:8080/nutzcn/user/seid
显示为:
r50n4677e0jkjpi5fqtkq5umnd,true
其中 r50n4677e0jkjpi5fqtkq5umnd 是session id, 后面是登录状态,为true,代表已经登录
然后使用Firefox浏览器, 访问
http://127.0.0.1:8080/nutzcn/user/logout/r50n4677e0jkjpi5fqtkq5umnd
页面无显示, 因为没东西, 后台也没有报错.
再使用Chrome访问
http://127.0.0.1:8080/nutzcn/user/seid
// 显示的内容是
66s1gij97gjmarjot93g8qrp40,false
// session id变了, 登录状态也变成未登录
// 再访问其他需要登录的页面,也跳到了登录页
所以, 根据上面的测试, 使用session id是可以把所属的session注销掉的
1,进行登录,显示登陆成功,然后同一个浏览器进行验证
98763A88673AC166B99A83EFD810A771,false,直接失败。。。
什么鬼
2,按照上面的方法,用另外一个非登陆浏览器进行退出session
请求的路径: /sysuser/logout/98763A88673AC166B99A83EFD810A771
异常堆栈如下:
java.lang.IllegalArgumentException: SessionKey must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.getSession(ServletContainerSessionManager.java:70)
at org.apache.shiro.mgt.SessionsSecurityManager.getSession(SessionsSecurityManager.java:156)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveContextSession(DefaultSecurityManager.java:456)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:442)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:338)
at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:846)
at com.binfoo.www.module.UserModule.logoutBySeid(UserModule.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:25)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.integration.shiro.NutShiroProcessor.process(NutShiroProcessor.java:126)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:22)
at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:198)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
要疯。。。
所有代码贴出来
package com.binfoo.www.module;
import javax.servlet.http.HttpSession;
import com.binfoo.www.bean.User;
import com.binfoo.www.bean.UserProfile;
import com.binfoo.www.service.UserService;
import com.binfoo.www.util.Toolkit;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.QueryResult;
import org.nutz.dao.pager.Pager;
import org.nutz.integration.shiro.SimpleShiroToken;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.Scope;
import org.nutz.mvc.annotation.*;
import static org.nutz.integration.jedis.RedisInterceptor.jedis;
@IocBean // 声明为Ioc容器中的一个Bean
@At("/sysuser") // 整个模块的路径前缀
@Ok("json:{locked:'password|salt',ignoreNull:true}") // 忽略password和salt属性,忽略空属性的json输出
@Fail("http:500") // 抛出异常的话,就走500页面
public class UserModule extends BaseModule {
private static final Log log = Logs.get();
private static final int MAX_USER_ONLINE = 2;
@Inject
protected UserService userService;
@Filters
@At
@Ok("raw")
public String seid(HttpSession session) {
return session.getId() + "," + SecurityUtils.getSubject().isAuthenticated();
}
@Filters
@At("/logout/?")
@Ok("http:200")
public void logoutBySeid(String seid) {
new Subject.Builder().sessionId(seid).buildSubject().logout();
}
@At
public int count() { // 统计用户数的方法,算是个测试点
return dao.count(User.class);
}
// 不允许后者登录
// Long re = jedis().setnx("u:sid:"+uid, sessionid);
// if (re == 0) {
// // 老session id存在, 检查一下是否过期. 如果没过期, 拒绝登录
// }
// shiro.login(...);
// String oldSessionId = jedis().getSet("u:sid:"+uid, sessionid);
// if (oldSessionId != null) {
// // 老session id存在, 取出session, 注销掉
// }
// shiro.login(...);
@At
@Aop("redis")
public Object login(@Param("username") String username, @Param("password") String password,
@Param("captcha") String captcha,
@Attr(scope = Scope.SESSION, value = "nutz_captcha") String _captcha, HttpSession session
) {
NutMap re = new NutMap();
if (!Toolkit.checkCaptcha(_captcha, captcha)) {
return re.setv("ok", false).setv("msg", "验证码错误");
}
int userId = userService.fetch(username, password);
try {
if (userId < 0) {
return re.setv("ok", false).setv("msg", "用户名或密码错误");
} else {
// Redis GETSET命令在Redis键中设置指定的字符串值,并返回其旧值。
//
// 返回值
//
// 返回一个字符串,也就是键的旧值。 如果键不存在,则返回nil。
String oldSessionId = jedis().getSet("u:sid:" + userId, session.getId());
log.info("sessionId = " + session.getId() + " ======== and oldSessionId = " + oldSessionId);
if (oldSessionId != null && !oldSessionId.equalsIgnoreCase(session.getId())) {
//取出来老的sessionId,然后注销掉,新登陆的踢掉老的用户
new Subject.Builder().sessionId(oldSessionId).buildSubject().logout();
}
// 完成nutdao_realm后启用.
SecurityUtils.getSubject().login(new SimpleShiroToken(userId));
//当前用户登录
session.setAttribute("me", userId);
}
} catch (Exception e) {
log.debug("老的会话已经过期");
session.setAttribute("me", userId);
return re.setv("ok", true);
}
return re.setv("ok", true);
}
@At
@Ok(">>:/") // 跟其他方法不同,这个方法完成后就跳转首页了
public void logout(HttpSession session) {
session.invalidate();
}
@At
@RequiresPermissions("sysuser:add")
public Object add(@Param("..") User user) { // 两个点号是按对象属性一一设置
NutMap re = new NutMap();
String msg = checkUser(user, true);
if (msg != null) {
return re.setv("ok", false).setv("msg", msg);
}
user = userService.add(user.getName(), user.getPassword());
return re.setv("ok", true).setv("data", user);
}
@At
@RequiresPermissions("sysuser:update")
public Object update(@Param("password") String password, @Attr("me") int me) {
if (Strings.isBlank(password) || password.length() < 6)
return new NutMap().setv("ok", false).setv("msg", "密码不符合要求");
userService.updatePassword(me, password);
return new NutMap().setv("ok", true);
}
@At
@Aop(TransAop.READ_COMMITTED)
@RequiresPermissions("sysuser:delete")
public Object delete(@Param("id") int id, @Attr("me") int me) {
if (me == id) {
return new NutMap().setv("ok", false).setv("msg", "不能删除当前用户!!");
}
dao.delete(User.class, id); // 再严谨一些的话,需要判断是否为>0
dao.clear(UserProfile.class, Cnd.where("userId", "=", me));
return new NutMap().setv("ok", true);
}
@At
// @RequiresPermissions("sysuser:query")
public Object query(@Param("name") String name, @Param("..") Pager pager) {
Cnd cnd = Strings.isBlank(name) ? null : Cnd.where("name", "like", "%" + name + "%");
QueryResult qr = new QueryResult();
qr.setList(dao.query(User.class, cnd, pager));
pager.setRecordCount(dao.count(User.class, cnd));
qr.setPager(pager);
return qr; //默认分页是第1页,每页20条
}
@At("/")
// @RequiresPermissions("sysuser:index")
@Ok("jsp:jsp.user.list") // 真实路径是 /WEB-INF/jsp/user/list.jsp
public void index() {
}
protected String checkUser(User user, boolean create) {
if (user == null) {
return "空对象";
}
if (create) {
if (Strings.isBlank(user.getName()) || Strings.isBlank(user.getPassword()))
return "用户名/密码不能为空";
} else {
if (Strings.isBlank(user.getPassword()))
return "密码不能为空";
}
String passwd = user.getPassword().trim();
if (6 > passwd.length() || passwd.length() > 12) {
return "密码长度错误";
}
user.setPassword(passwd);
if (create) {
int count = dao.count(User.class, Cnd.where("name", "=", user.getName()));
if (count != 0) {
return "用户名已经存在";
}
} else {
if (user.getId() < 1) {
return "用户Id非法";
}
}
if (user.getName() != null)
user.setName(user.getName().trim());
return null;
}
@GET
@At("/login")
@Ok("jsp:jsp.user.login") // 将内部重定向到登录jsp
public void loginPage() {
}
}
这句要单独try catch的. 不然老session id有任何异常,新的session都不可能登录成功
try {
new Subject.Builder().sessionId(oldSessionId).buildSubject().logout();
} catch (Exception) {}
http://127.0.0.1:8080/nutzcn/user/seid 要出true, 才代表登录成功了
true可以了,退出的时候报错
应该是seid类型我看shiro是序列化的,我用string是错的
要怎么转换
java.lang.IllegalArgumentException: SessionKey must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.getSession(ServletContainerSessionManager.java:70)
at org.apache.shiro.mgt.SessionsSecurityManager.getSession(SessionsSecurityManager.java:156)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveContextSession(DefaultSecurityManager.java:456)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:442)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:338)
at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:846)
at com.binfoo.www.module.UserModule.logoutBySeid(UserModule.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:25)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.integration.shiro.NutShiroProcessor.process(NutShiroProcessor.java:126)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:22)
at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:198)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
[main]
nutzdao_realm = com.binfoo.www.shiro.realm.SimpleAuthorizingRealm
cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml
nutzdao_realm.cacheManager = $cacheManager
authc = org.nutz.integration.shiro.SimpleAuthenticationFilter
authc.loginUrl = /sysuser/login
logout.redirectUrl = /sysuser/login
[urls]
/rs/* = anon, noSessionCreation
/sysuser/logout = logout
/sysuser/error = anon
/sysuser/login = anon
/sysuser/profile/active/mail = anon
var ioc = {
// "cacheManager" : {
// "type" : "net.sf.ehcache.CacheManager",
// "factory" : "net.sf.ehcache.CacheManager#getCacheManager",
// "args" : ["bms"] // 对应shiro.ini中指定的ehcache.xml中定义的name
// }
// 如果不需要shiro初始化的Ehcache, 使用下面的方式配置
"cacheManager" : {
"type" : "net.sf.ehcache.CacheManager",
"factory" : "net.sf.ehcache.CacheManager#create"
}
};
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false"
monitoring="autodetect" dynamicConfig="true" name="bms">
<!-- <diskStore path="java.io.tmpdir/shiro-ehcache"/> -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
<cache name="shiro-activeSessionCache"
maxElementsInMemory="10000"
overflowToDisk="true"
eternal="true"
timeToLiveSeconds="0"
timeToIdleSeconds="0"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="600"/>
</ehcache>
shiro版本差异? 先不管了. 既然它要求"SessionKey must be an HTTP compatible implementation", 那就给它个合法的:
new Subject.Builder().sessionId(new WebSessionKey(oldSessionId, Mvcs.getReq(), Mvcs.getResp())).buildSubject().logout();
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
依然报错,兽总辛苦
package com.binfoo.www.module;
import javax.servlet.http.HttpSession;
import com.binfoo.www.bean.User;
import com.binfoo.www.bean.UserProfile;
import com.binfoo.www.service.UserService;
import com.binfoo.www.util.Toolkit;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.session.mgt.WebSessionKey;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.QueryResult;
import org.nutz.dao.pager.Pager;
import org.nutz.integration.shiro.SimpleShiroToken;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.Scope;
import org.nutz.mvc.annotation.*;
import java.io.Serializable;
import static org.nutz.integration.jedis.RedisInterceptor.jedis;
@IocBean // 声明为Ioc容器中的一个Bean
@At("/sysuser") // 整个模块的路径前缀
@Ok("json:{locked:'password|salt',ignoreNull:true}") // 忽略password和salt属性,忽略空属性的json输出
@Fail("http:500") // 抛出异常的话,就走500页面
public class UserModule extends BaseModule {
private static final Log log = Logs.get();
private static final int MAX_USER_ONLINE = 2;
@Inject
protected UserService userService;
@Filters
@At
@Ok("raw")
public String seid(HttpSession session) {
return session.getId() + "," + SecurityUtils.getSubject().isAuthenticated();
}
@Filters
@At("/forcelogout/?")
@Ok("http:200")
public void logoutBySeid(String seid) {
new Subject.Builder().sessionId(new WebSessionKey(seid, Mvcs.getReq(), Mvcs.getResp())).buildSubject().logout();
}
@At
public int count() { // 统计用户数的方法,算是个测试点
return dao.count(User.class);
}
// 不允许后者登录
// Long re = jedis().setnx("u:sid:"+uid, sessionid);
// if (re == 0) {
// // 老session id存在, 检查一下是否过期. 如果没过期, 拒绝登录
// }
// shiro.login(...);
// String oldSessionId = jedis().getSet("u:sid:"+uid, sessionid);
// if (oldSessionId != null) {
// // 老session id存在, 取出session, 注销掉
// }
// shiro.login(...);
@At
@Aop("redis")
public Object login(@Param("username") String username, @Param("password") String password,
@Param("captcha") String captcha,
@Attr(scope = Scope.SESSION, value = "nutz_captcha") String _captcha, HttpSession session
) {
NutMap re = new NutMap();
if (!Toolkit.checkCaptcha(_captcha, captcha)) {
return re.setv("ok", false).setv("msg", "验证码错误");
}
int userId = userService.fetch(username, password);
if (userId < 0) {
return re.setv("ok", false).setv("msg", "用户名或密码错误");
} else {
// Redis GETSET命令在Redis键中设置指定的字符串值,并返回其旧值。
//
// 返回值
//
// 返回一个字符串,也就是键的旧值。 如果键不存在,则返回nil。
String oldSessionId = jedis().getSet("u:sid:" + userId, session.getId());
log.info("sessionId = " + session.getId() + " ======== and oldSessionId = " + oldSessionId);
if (oldSessionId != null && !oldSessionId.equalsIgnoreCase(session.getId())) {
//取出来老的sessionId,然后注销掉,新登陆的踢掉老的用户
try {
// new Subject.Builder().sessionId(oldSessionId).buildSubject().logout();
new Subject.Builder().sessionId(new WebSessionKey(oldSessionId, Mvcs.getReq(), Mvcs.getResp())).buildSubject().logout();
} catch (Exception e) {
}
}
// 完成nutdao_realm后启用.
SecurityUtils.getSubject().login(new SimpleShiroToken(userId));
//当前用户登录
session.setAttribute("me", userId);
}
return re.setv("ok", true);
}
@At
@Ok(">>:/") // 跟其他方法不同,这个方法完成后就跳转首页了
public void logout(HttpSession session) {
session.invalidate();
}
@At
@RequiresPermissions("sysuser:add")
public Object add(@Param("..") User user) { // 两个点号是按对象属性一一设置
NutMap re = new NutMap();
String msg = checkUser(user, true);
if (msg != null) {
return re.setv("ok", false).setv("msg", msg);
}
user = userService.add(user.getName(), user.getPassword());
return re.setv("ok", true).setv("data", user);
}
@At
@RequiresPermissions("sysuser:update")
public Object update(@Param("password") String password, @Attr("me") int me) {
if (Strings.isBlank(password) || password.length() < 6)
return new NutMap().setv("ok", false).setv("msg", "密码不符合要求");
userService.updatePassword(me, password);
return new NutMap().setv("ok", true);
}
@At
@Aop(TransAop.READ_COMMITTED)
@RequiresPermissions("sysuser:delete")
public Object delete(@Param("id") int id, @Attr("me") int me) {
if (me == id) {
return new NutMap().setv("ok", false).setv("msg", "不能删除当前用户!!");
}
dao.delete(User.class, id); // 再严谨一些的话,需要判断是否为>0
dao.clear(UserProfile.class, Cnd.where("userId", "=", me));
return new NutMap().setv("ok", true);
}
@At
// @RequiresPermissions("sysuser:query")
public Object query(@Param("name") String name, @Param("..") Pager pager) {
Cnd cnd = Strings.isBlank(name) ? null : Cnd.where("name", "like", "%" + name + "%");
QueryResult qr = new QueryResult();
qr.setList(dao.query(User.class, cnd, pager));
pager.setRecordCount(dao.count(User.class, cnd));
qr.setPager(pager);
return qr; //默认分页是第1页,每页20条
}
@At("/")
// @RequiresPermissions("sysuser:index")
@Ok("jsp:jsp.user.list") // 真实路径是 /WEB-INF/jsp/user/list.jsp
public void index() {
}
protected String checkUser(User user, boolean create) {
if (user == null) {
return "空对象";
}
if (create) {
if (Strings.isBlank(user.getName()) || Strings.isBlank(user.getPassword()))
return "用户名/密码不能为空";
} else {
if (Strings.isBlank(user.getPassword()))
return "密码不能为空";
}
String passwd = user.getPassword().trim();
if (6 > passwd.length() || passwd.length() > 12) {
return "密码长度错误";
}
user.setPassword(passwd);
if (create) {
int count = dao.count(User.class, Cnd.where("name", "=", user.getName()));
if (count != 0) {
return "用户名已经存在";
}
} else {
if (user.getId() < 1) {
return "用户Id非法";
}
}
if (user.getName() != null)
user.setName(user.getName().trim());
return null;
}
@GET
@At("/login")
@Ok("jsp:jsp.user.login") // 将内部重定向到登录jsp
public void loginPage() {
}
}
前面版本对不上,现在的maven改了
2017-04-11 09:05:08,895 org.nutz.mvc.impl.processor.FailProcessor.process(FailProcessor.java:28) WARN - Error@/sysuser/forcelogout/118E5A81FE10728451821CD7F3566116 :
java.lang.IllegalArgumentException: SessionKey must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.getSession(ServletContainerSessionManager.java:70)
at org.apache.shiro.mgt.SessionsSecurityManager.getSession(SessionsSecurityManager.java:156)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveContextSession(DefaultSecurityManager.java:456)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:442)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:338)
at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:846)
at com.binfoo.www.module.UserModule.logoutBySeid(UserModule.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:25)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.integration.shiro.NutShiroProcessor.process(NutShiroProcessor.java:126)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:22)
at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:198)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
@Filters
@At("/forcelogout/?")
@Ok("http:200")
public void logoutBySeid(String seid) {
// new Subject.Builder().sessionId(new WebSessionKey(seid, Mvcs.getReq(), Mvcs.getResp())).buildSubject().logout();
new Subject.Builder().sessionId(seid).buildSubject().logout();
}
两种同样的错误
@binfoo 用WebSessionKey,贴它的出错信息
第58行对应
new Subject.Builder().sessionId(new WebSessionKey(seid, Mvcs.getReq(), Mvcs.getResp())).buildSubject().logout();
2017-04-11 09:12:20,510 com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:27) DEBUG - [ GET]URI=/sysuser/forcelogout/F575602A34199F7FE52F83EF891A0024 0ms
2017-04-11 09:12:20,510 org.nutz.mvc.impl.processor.FailProcessor.process(FailProcessor.java:28) WARN - Error@/sysuser/forcelogout/F575602A34199F7FE52F83EF891A0024 :
java.lang.IllegalArgumentException: SessionKey must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.getSession(ServletContainerSessionManager.java:70)
at org.apache.shiro.mgt.SessionsSecurityManager.getSession(SessionsSecurityManager.java:156)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveContextSession(DefaultSecurityManager.java:456)
at org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:442)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:338)
at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:846)
at com.binfoo.www.module.UserModule.logoutBySeid(UserModule.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:25)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.integration.shiro.NutShiroProcessor.process(NutShiroProcessor.java:126)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at com.binfoo.www.mvc.LogTimeProcessor.process(LogTimeProcessor.java:22)
at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:198)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
2017-04-11 09:12:24,317 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
2017-04-11 09:12:47,448 org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:276) DEBUG - batch acquisition of 0 triggers
换个思路
问题出在ServletContainerSessionManager, 而这个用的是 容器Session, 那我们换掉它
http://shiro.apache.org/web.html#native-sessions
[main]
# 加这句
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
然后,sessionId用回字符串, 不走WebSessionId了
public void logoutBySeid(String seid) {
new Subject.Builder().sessionId(seid).buildSubject().logout();
}