返回

无缝整合Springboot、Dubbo与Shiro,解决用户信息获取难题

后端

当 Springboot 邂逅 Dubbo,Shiro 为何迷失了方向?

导言

Springboot 的强大整合能力与 Dubbo 微服务架构的灵活性相结合,为开发者创造了无限可能。然而,在集成这两个框架时,一个常见的痛点浮出水面—— Shiro 无法获取用户信息。本文将深入探讨这一问题,并提供切实可行的解决方案。

问题根源:上下文断层

造成 Shiro 无法获取用户信息的原因在于上下文断层。Springboot 和 Dubbo 拥有独立的上下文,当 Springboot 整合 Dubbo 时,两者的上下文并没有有机融合。这导致 Shiro 无法在 Dubbo 的上下文中获取用户信息。

解决方案:会话管理器

要解决这个问题,我们需要找到一种方法让 Shiro 能够在 Dubbo 的上下文中获取用户信息。一种常用的解决方案是使用 Shiro 的“会话管理器”(Session Manager)。通过配置会话管理器,我们可以将用户的身份信息存储在 Dubbo 的上下文中。

详细步骤:

1. 引入依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.7.7</version>
</dependency>

2. 配置 Shiro:

@Configuration
public class ShiroConfig {

    @Bean
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(60 * 60 * 1000);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setDeleteInvalidSessions(true);
        return sessionManager;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        securityManager.setRealm(realm());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    @Bean
    public Realm realm() {
        ShiroRealm realm = new ShiroRealm();
        return realm;
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new ShiroFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE);
        return filterRegistrationBean;
    }
}

3. 实现 Realm:

public class ShiroRealm extends AuthorizingRealm {

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        String password = (String) token.getCredentials();
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("用户不存在");
        }
        if (!user.getPassword().equals(password)) {
            throw new IncorrectCredentialsException("密码错误");
        }
        return new SimpleAuthenticationInfo(username, password, getName());
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        Set<String> roles = userService.findRolesByUsername(username);
        Set<String> permissions = userService.findPermissionsByUsername(username);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }
}

结论:告别烦恼,拥抱顺畅

通过上述步骤,你将能够轻松解决 Springboot 整合 Dubbo 时,Shiro 获取不到用户信息的问题。告别烦恼,享受顺畅开发之旅!

常见问题解答

  1. 为什么需要使用会话管理器?

会话管理器允许我们在 Dubbo 的上下文中存储用户的身份信息,以便 Shiro 可以访问这些信息。

  1. 除了会话管理器,还有其他解决方案吗?

可以使用 Dubbo 的过滤器链,但会话管理器更简单、更常用。

  1. 如何配置会话管理器的超时时间?

使用 setGlobalSessionTimeout(60 * 60 * 1000) 方法,单位为毫秒。

  1. 如何自定义 Shiro 的 Realm?

通过实现 Realm 接口并覆盖 doGetAuthenticationInfodoGetAuthorizationInfo 方法。

  1. 在 Springboot 中使用 Shiro 的最佳实践是什么?

将 Shiro 集成到 Spring Security 中,以利用其丰富的功能。