修改shiro 兼容性问题

This commit is contained in:
wh
2026-04-13 19:58:49 +08:00
parent 5d74578aa3
commit e8235eeec5
6 changed files with 94 additions and 61 deletions

View File

@@ -0,0 +1,39 @@
package com.label.unit;
import com.label.common.redis.RedisService;
import com.label.common.shiro.ShiroConfig;
import com.label.common.shiro.UserRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.Mockito.mock;
@DisplayName("ShiroConfig 单元测试")
class ShiroConfigTest {
@AfterEach
void tearDown() {
org.apache.shiro.util.ThreadContext.remove();
}
@Test
@DisplayName("securityManager 不应依赖 DefaultWebSecurityManager以避免 javax.servlet 兼容性问题")
void securityManager_shouldNotDependOnDefaultWebSecurityManager() {
ShiroConfig config = new ShiroConfig();
RedisService redisService = mock(RedisService.class);
UserRealm realm = config.userRealm(redisService);
SecurityManager securityManager = config.securityManager(realm);
assertThat(securityManager).isNotInstanceOf(DefaultWebSecurityManager.class);
ThreadContext.bind(securityManager);
assertThatCode(SecurityUtils::getSubject).doesNotThrowAnyException();
}
}

View File

@@ -4,18 +4,12 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.label.common.context.CompanyContext;
import com.label.common.redis.RedisKeyManager;
import com.label.common.redis.RedisService;
import com.label.common.shiro.BearerToken;
import com.label.common.shiro.ShiroConfig;
import com.label.common.shiro.TokenFilter;
import com.label.common.shiro.TokenPrincipal;
import com.label.common.shiro.UserRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ThreadContext;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -38,12 +32,15 @@ class TokenFilterTest {
private RedisService redisService;
private TestableTokenFilter filter;
private DefaultSecurityManager securityManager;
@BeforeEach
void setUp() {
redisService = mock(RedisService.class);
filter = new TestableTokenFilter(redisService, new ObjectMapper());
SecurityUtils.setSecurityManager(new DefaultSecurityManager(new BearerTokenRealm()));
UserRealm userRealm = new UserRealm(redisService);
securityManager = (DefaultSecurityManager) new ShiroConfig().securityManager(userRealm);
filter = new TestableTokenFilter(redisService, new ObjectMapper(), securityManager);
SecurityUtils.setSecurityManager(securityManager);
}
@AfterEach
@@ -74,6 +71,7 @@ class TokenFilterTest {
assertThat(response.getStatus()).isEqualTo(200);
assertThat(chain.principal).isInstanceOf(TokenPrincipal.class);
assertThat(chain.roleChecked).isTrue();
verify(redisService).expire(RedisKeyManager.tokenKey(token), 7200L);
}
@@ -98,41 +96,26 @@ class TokenFilterTest {
assertThat(principal.getUserId()).isEqualTo(4L);
assertThat(principal.getRole()).isEqualTo("ADMIN");
assertThat(principal.getUsername()).isEqualTo("mock-admin");
assertThat(chain.roleChecked).isTrue();
verify(redisService, never()).hGetAll(anyString());
}
private static final class BearerTokenRealm extends AuthorizingRealm {
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof BearerToken;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
return new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
TokenPrincipal principal = (TokenPrincipal) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRole(principal.getRole());
return info;
}
}
private static final class RecordingChain implements FilterChain {
private TokenPrincipal principal;
private boolean roleChecked;
@Override
public void doFilter(ServletRequest request, ServletResponse response) {
principal = (TokenPrincipal) request.getAttribute("__token_principal__");
SecurityUtils.getSubject().checkRole(principal.getRole());
roleChecked = true;
}
}
private static final class TestableTokenFilter extends TokenFilter {
private TestableTokenFilter(RedisService redisService, ObjectMapper objectMapper) {
super(redisService, objectMapper);
private TestableTokenFilter(RedisService redisService, ObjectMapper objectMapper,
DefaultSecurityManager securityManager) {
super(redisService, objectMapper, securityManager);
}
private void invoke(MockHttpServletRequest request, MockHttpServletResponse response, FilterChain chain)