强制登出所有用户,每次升级之前强制用户重新登录No SecurityManager accessible to the calling code, either bound to the org.ap
原创
君子志邦2022-05-17 15:03:39博主文章分类:2021年工作©著作权
文章标签强制登出所有用户升级前提出登录踢出登录用户springjava文章分类Spark大数据阅读数227
解决办法:在 ShiroConfig.java 中的方法
public SecurityManager securityManager(UserRealm userRealm, SpringSessionValidationScheduler springSessionValidationScheduler)中添加:ThreadContext.bind(securityManager);
错误信息:
异常信息:
2021-01-0709:39:16.299|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:queryTagsByCategory
2021-01-0709:39:16.332|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:queryTagsByTagValue
2021-01-0709:39:16.345|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:registerTags
2021-01-0709:39:51.590|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:queryConditionList
2021-01-0709:40:24.033|ERROR|main|845|o.s.boot.SpringApplication :Applicationrunfailed
java.lang.IllegalStateException: FailedtoexecuteCommandLineRunner
atorg.springframework.boot.SpringApplication.callRunner(SpringApplication.java:803)
atorg.springframework.boot.SpringApplication.callRunners(SpringApplication.java:784)
atorg.springframework.boot.SpringApplication.run(SpringApplication.java:338)
atorg.gil.three.admin.ThreeAdminApplication.main(ThreeAdminApplication.java:35)
Causedby: org.apache.shiro.UnavailableSecurityManagerException: NoSecurityManageraccessibletothecallingcode, eitherboundtotheorg.apache.shiro.util.ThreadContextorasavmstaticsingleton. Thisisaninvalidapplicationconfiguration.
atorg.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
atorg.gil.three.admin.util.ShiroUtil.kickOutAllUsers(ShiroUtil.java:109)
atorg.gil.three.admin.runner.RedisFlushCommandLineRunner.run(RedisFlushCommandLineRunner.java:42)
atorg.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800)
... 3commonframesomitted
java.lang.IllegalStateException: FailedtoexecuteCommandLineRunner
atorg.springframework.boot.SpringApplication.callRunner(SpringApplication.java:803)
atorg.springframework.boot.SpringApplication.callRunners(SpringApplication.java:784)
atorg.springframework.boot.SpringApplication.run(SpringApplication.java:338)
atorg.gil.three.admin.ThreeAdminApplication.main(ThreeAdminApplication.java:35)
Causedby: org.apache.shiro.UnavailableSecurityManagerException: NoSecurityManageraccessibletothecallingcode, eitherboundtotheorg.apache.shiro.util.ThreadContextorasavmstaticsingleton. Thisisaninvalidapplicationconfiguration.
atorg.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
atorg.gil.three.admin.util.ShiroUtil.kickOutAllUsers(ShiroUtil.java:109)
atorg.gil.three.admin.runner.RedisFlushCommandLineRunner.run(RedisFlushCommandLineRunner.java:42)
atorg.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800)
... 3more
DisconnectedfromthetargetVM, address: '127.0.0.1:12507', transport: 'socket'
Processfinishedwithexitcode-1

文字描述:
Caused by: org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
at org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
at org.gil.three.admin.util.ShiroUtil.kickOutAllUsers(ShiroUtil.java:109)
at org.gil.three.admin.runner.RedisFlushCommandLineRunner.run(RedisFlushCommandLineRunner.java:42)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800)
... 3 common frames omitted
主要是类的获取有问题,静态方法没有实例化类,所以获取有问题
importjava.util.Collection;
importjava.util.Objects;
importorg.apache.shiro.SecurityUtils;
importorg.apache.shiro.authc.Authenticator;
importorg.apache.shiro.authc.LogoutAware;
importorg.apache.shiro.session.Session;
importorg.apache.shiro.subject.SimplePrincipalCollection;
importorg.apache.shiro.subject.support.DefaultSubjectContext;
importorg.apache.shiro.web.mgt.DefaultWebSecurityManager;
importorg.crazycake.shiro.RedisSessionDAO;
importorg.gil.three.admin.model.vo.SessionUser;
publicclassShiroUtil {
privatestaticRedisSessionDAOredisSessionDAO=SpringUtil
.getBean(RedisSessionDAO.class);
privateShiroUtil() {
}
/**
* 获取指定用户名的Session
* @param username
* @return
*/
privatestaticSessiongetSessionByUsername(Stringusername) {
Collection<Session>sessions=redisSessionDAO.getActiveSessions();
SessionUseruser;
Objectattribute;
for (Sessionsession : sessions) {
attribute=session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute==null) {
continue;
}
user= (SessionUser) ((SimplePrincipalCollection) attribute)
.getPrimaryPrincipal();
if (user==null) {
continue;
}
if (Objects.equals(user.getUserName(), username)) {
returnsession;
}
}
returnnull;
}
/**
* 删除用户缓存信息
* @param username 用户名
* @param isRemoveSession 是否删除session,删除后用户需重新登录
*/
publicstaticvoidkickOutUser(Stringusername, booleanisRemoveSession) {
Sessionsession=getSessionByUsername(username);
if (session==null) {
return;
}
Objectattribute=session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute==null) {
return;
}
SessionUseruser= (SessionUser) ((SimplePrincipalCollection) attribute)
.getPrimaryPrincipal();
if (!username.equals(user.getUserName())) {
return;
}
// 删除session
if (isRemoveSession) {
redisSessionDAO.delete(session);
}
DefaultWebSecurityManagersecurityManager= (DefaultWebSecurityManager) SecurityUtils
.getSecurityManager();
Authenticatorauthc=securityManager.getAuthenticator();
// 删除cache,在访问受限接口时会重新授权
((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
}
}
解决办法:
@Autowired
private AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor;
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) authorizationAttributeSourceAdvisor.getSecurityManager();
Authenticator authc = securityManager.getAuthenticator();
authorizationAttributeSourceAdvisor在shiroconfig配置的里面声明bean,这里注入,然后直接就可以获取到了
修改之后的实现类:
登录后复制
importlombok.extern.slf4j.Slf4j;
importorg.apache.shiro.SecurityUtils;
importorg.apache.shiro.authc.Authenticator;
importorg.apache.shiro.authc.LogoutAware;
importorg.apache.shiro.session.Session;
importorg.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
importorg.apache.shiro.subject.SimplePrincipalCollection;
importorg.apache.shiro.subject.support.DefaultSubjectContext;
importorg.apache.shiro.web.mgt.DefaultWebSecurityManager;
importorg.gil.three.admin.config.shiro.ShiroResdisSessionDAO;
importorg.gil.three.admin.model.vo.SessionUser;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Component;
importjava.util.Collection;
importjava.util.Objects;
@Component
@Slf4j
publicclassShiroUtil {
@Autowired
privateShiroResdisSessionDAOshiroResdisSessionDAO;
@Autowired
privateAuthorizationAttributeSourceAdvisorauthorizationAttributeSourceAdvisor;
privateShiroUtil() {
}
/**
* 获取指定用户名的Session
*
* @param username
* @return
*/
privateSessiongetSessionByUsername(Stringusername) {
Collection<Session>sessions=shiroResdisSessionDAO.getActiveSessions();
SessionUseruser;
Objectattribute;
for (Sessionsession : sessions) {
attribute=session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute==null) {
continue;
}
user= (SessionUser) ((SimplePrincipalCollection) attribute)
.getPrimaryPrincipal();
if (user==null) {
continue;
}
if (Objects.equals(user.getUserName(), username)) {
returnsession;
}
}
returnnull;
}
/**
* 删除用户缓存信息
*
* @param username 用户名
* @param isRemoveSession 是否删除session,删除后用户需重新登录
*/
publicvoidkickOutUser(Stringusername, booleanisRemoveSession) {
Sessionsession=getSessionByUsername(username);
if (session==null) {
return;
}
Objectattribute=session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute==null) {
return;
}
SessionUseruser= (SessionUser) ((SimplePrincipalCollection) attribute)
.getPrimaryPrincipal();
if (!username.equals(user.getUserName())) {
return;
}
// 删除session
if (isRemoveSession) {
shiroResdisSessionDAO.delete(session);
}
DefaultWebSecurityManagersecurityManager= (DefaultWebSecurityManager) SecurityUtils
.getSecurityManager();
Authenticatorauthc=securityManager.getAuthenticator();
// 删除cache,在访问受限接口时会重新授权
((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
}
publicvoidkickOutAllUsers() {
Collection<Session>sessions=shiroResdisSessionDAO.getActiveSessions();
SessionUseruser;
Objectattribute;
for (Sessionsession : sessions) {
attribute=session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute==null) {
continue;
}
user= (SessionUser) ((SimplePrincipalCollection) attribute).getPrimaryPrincipal();
if (user==null) {
continue;
}
shiroResdisSessionDAO.delete(session);
DefaultWebSecurityManagersecurityManager= (DefaultWebSecurityManager) authorizationAttributeSourceAdvisor.getSecurityManager();
Authenticatorauthc=securityManager.getAuthenticator();
// 删除cache,在访问受限接口时会重新授权
((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
log.error("用户强制登出,用户名:{},用户id:{}",user.getRealName(),user.getId());
}
}
}