问题复现
登录逻辑处理
问题怎么出现的?
这个问题是shiro默认注入了两次Realm,默认是list集合
解决思路
重载SessionsSecurityManager securityManager方法或者重写SessionsSecurityManager securityManager方法
解决方法参考代码:
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
SessionsSecurityManager securityManager =super.securityManager(realms);
//手动注入自己的Realm,不使用shiro的自动注入
securityManager.setRealm(sampleRealm());
return securityManager;
}
完整参考Java代码
import java.util.List;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import lombok.extern.slf4j.Slf4j;
@SpringBootConfiguration
@Slf4j
public class BootShiroWebAutoConfiguration extends ShiroWebAutoConfiguration {
@Autowired
RedisSessionDAO redisSessionDAO;
/**
* <p>@方法名描述 : Shiro过滤器 </p>
* <per>
* <code>
* anon ===> 开放路径,允许匿名访问,不需要权限和不需要登录就可以访问
* authc ===> 需要登录后才可以访问路径
* </code>
* </per>
* @return
*/
@Bean("shiroFilterChainDefinition")
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/api/doLogin", "anon");
// chainDefinition.addPathDefinition("/**", "authc");
chainDefinition.addPathDefinition("/**", "authc,jwt");
// chainDefinition.addPathDefinition("/**", "authc");
// chainDefinition.addPathDefinition("/**", "jwt");
return chainDefinition;
}
//重写这个方法解决,方案一
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
SessionsSecurityManager securityManager =super.securityManager(realms);
securityManager.setRealm(sampleRealm());
return securityManager;
}
//或者重载这个方法,方案二
protected SessionsSecurityManager securityManager(Realm realms) {
SessionsSecurityManager securityManager =super.securityManager(null);
securityManager.setRealm(sampleRealm());
return securityManager;
}
/**
* <p>@Bean("authorizer") 是必须的</>
* <p>自定义 Realm</>
* @return 自定义 SampleRealm 对象
*/
@Bean("authorizer")
Realm sampleRealm() {
return new SampleRealm();
}
/**
* <p>重写SessionDAO</>
* <p>SessionDAO 默认实现交由 RedisSessionDAO 实现管理</p>
*/
@Override
protected SessionDAO sessionDAO() {
return redisSessionDAO;
}
}
参考pom坐标
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.10.1</version>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis-spring-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.10.1</version>
</dependency>