强制登出所有用户,每次升级之前强制用户重新登录No SecurityManager accessible to the calling code, either bound to the org.ap
异常信息:
2021-01-07 09:39:16.299|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:queryTagsByCategory
2021-01-07 09:39:16.332|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:queryTagsByTagValue
2021-01-07 09:39:16.345|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:registerTags
2021-01-07 09:39:51.590|ERROR|main|212|c.h.j.rpc.t2.util.ServiceDefinitionUtil :解析接口方法异常: method:queryConditionList
2021-01-07 09:40:24.033|ERROR|main|845|o.s.boot.SpringApplication :Application run failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:803)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:784)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.gil.three.admin.ThreeAdminApplication.main(ThreeAdminApplication.java:35)
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
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:803)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:784)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.gil.three.admin.ThreeAdminApplication.main(ThreeAdminApplication.java:35)
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 more
Disconnected from the target VM, address: '127.0.0.1:12507', transport: 'socket'
Process finished with exit code -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
主要是类的获取有问题,静态方法没有实例化类,所以获取有问题
import java.util.Collection;
import java.util.Objects;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.LogoutAware;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.gil.three.admin.model.vo.SessionUser;
public class ShiroUtil {
private static RedisSessionDAO redisSessionDAO = SpringUtil
.getBean(RedisSessionDAO.class);
private ShiroUtil() {
}
/**
* 获取指定用户名的Session
* @param username
* @return
*/
private static Session getSessionByUsername(String username) {
Collection<Session> sessions = redisSessionDAO.getActiveSessions();
SessionUser user;
Object attribute;
for (Session session : 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)) {
return session;
}
}
return null;
}
/**
* 删除用户缓存信息
* @param username 用户名
* @param isRemoveSession 是否删除session,删除后用户需重新登录
*/
public static void kickOutUser(String username, boolean isRemoveSession) {
Session session = getSessionByUsername(username);
if (session == null) {
return;
}
Object attribute = session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute == null) {
return;
}
SessionUser user = (SessionUser) ((SimplePrincipalCollection) attribute)
.getPrimaryPrincipal();
if (!username.equals(user.getUserName())) {
return;
}
// 删除session
if (isRemoveSession) {
redisSessionDAO.delete(session);
}
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils
.getSecurityManager();
Authenticator authc = securityManager.getAuthenticator();
// 删除cache,在访问受限接口时会重新授权
((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
}
}
解决办法:
@Autowired
private AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor;
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) authorizationAttributeSourceAdvisor.getSecurityManager();
Authenticator authc = securityManager.getAuthenticator();
authorizationAttributeSourceAdvisor在shiroconfig配置的里面声明bean,这里注入,然后直接就可以获取到了
修改之后的实现类:
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.LogoutAware;
import org.apache.shiro.session.Session;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.gil.three.admin.config.shiro.ShiroResdisSessionDAO;
import org.gil.three.admin.model.vo.SessionUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Objects;
@Component
@Slf4j
public class ShiroUtil {
@Autowired
private ShiroResdisSessionDAO shiroResdisSessionDAO;
@Autowired
private AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor;
private ShiroUtil() {
}
/**
* 获取指定用户名的Session
*
* @param username
* @return
*/
private Session getSessionByUsername(String username) {
Collection<Session> sessions = shiroResdisSessionDAO.getActiveSessions();
SessionUser user;
Object attribute;
for (Session session : 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)) {
return session;
}
}
return null;
}
/**
* 删除用户缓存信息
*
* @param username 用户名
* @param isRemoveSession 是否删除session,删除后用户需重新登录
*/
public void kickOutUser(String username, boolean isRemoveSession) {
Session session = getSessionByUsername(username);
if (session == null) {
return;
}
Object attribute = session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute == null) {
return;
}
SessionUser user = (SessionUser) ((SimplePrincipalCollection) attribute)
.getPrimaryPrincipal();
if (!username.equals(user.getUserName())) {
return;
}
// 删除session
if (isRemoveSession) {
shiroResdisSessionDAO.delete(session);
}
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils
.getSecurityManager();
Authenticator authc = securityManager.getAuthenticator();
// 删除cache,在访问受限接口时会重新授权
((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
}
public void kickOutAllUsers() {
Collection<Session> sessions = shiroResdisSessionDAO.getActiveSessions();
SessionUser user;
Object attribute;
for (Session session : sessions) {
attribute = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute == null) {
continue;
}
user = (SessionUser) ((SimplePrincipalCollection) attribute).getPrimaryPrincipal();
if (user == null) {
continue;
}
shiroResdisSessionDAO.delete(session);
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) authorizationAttributeSourceAdvisor.getSecurityManager();
Authenticator authc = securityManager.getAuthenticator();
// 删除cache,在访问受限接口时会重新授权
((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
log.error("用户强制登出,用户名:{},用户id:{}",user.getRealName(),user.getId());
}
}
}
还没有评论,来说两句吧...