Shiro扩展与集成实战指南

一、Spring/Spring Boot整合

自动化配置原理

Spring Boot通过ShiroAutoConfiguration自动配置核心组件,开发者只需定义RealmSecurityManager即可完成基础整合。

@Configuration
public class ShiroConfig {
    @Bean
    public Realm customRealm() {
        return new CustomRealm();
    }
    
    @Bean
    public SecurityManager securityManager(Realm realm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(realm);
        return manager;
    }
}

实践建议

  1. 使用@DependsOn注解明确Bean依赖顺序
  2. 通过application.yml配置Shiro基础参数:

    shiro:
      enabled: true
      loginUrl: /login
      successUrl: /home

二、Web集成机制

Filter链工作原理

Shiro通过过滤器链实现URL级安全控制,典型配置示例:

@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean factory = new ShiroFilterFactoryBean();
    factory.setSecurityManager(securityManager);
    
    Map<String, String> filterMap = new LinkedHashMap<>();
    filterMap.put("/static/**", "anon");
    filterMap.put("/login", "anon");
    filterMap.put("/admin/**", "authc, roles[admin]");
    filterMap.put("/**", "user");
    
    factory.setFilterChainDefinitionMap(filterMap);
    return factory;
}

过滤器类型

  • anon:匿名访问
  • authc:需要认证
  • user:记住我用户可访问
  • perms:需要特定权限

图1

三、数据库集成方案

JDBC Realm配置

public class JdbcRealm extends AuthorizingRealm {
    @Autowired
    private DataSource dataSource;
    
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        String sql = "SELECT password, salt FROM users WHERE username = ?";
        try (Connection conn = dataSource.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            // 执行查询并构建AuthenticationInfo
        }
    }
}

性能优化

  1. 实现CachingRealm接口启用缓存
  2. 使用SimpleAuthenticationInfo传递盐值
  3. 密码比对建议:

    ByteSource salt = ByteSource.Util.bytes(user.getSalt());
    return new SimpleAuthenticationInfo(
     username, 
     user.getPassword(),
     salt,
     getName()
    );

四、OAuth2集成策略

适配流程

  1. 自定义OAuth2Token:

    public class OAuth2Token implements AuthenticationToken {
     private String accessToken;
     // getters/setters...
    }
  2. 实现OAuth2Realm:

    public class OAuth2Realm extends AuthorizingRealm {
     public boolean supports(AuthenticationToken token) {
         return token instanceof OAuth2Token;
     }
     
     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
         String accessToken = (String) token.getPrincipal();
         // 调用OAuth2 provider验证token
     }
    }

关键配置

@Bean
public DefaultFilterChainManager filterChainManager() {
    DefaultFilterChainManager manager = new DefaultFilterChainManager();
    manager.addFilter("oauth2", new OAuth2Filter());
    return manager;
}

五、多Realm协同方案

策略配置示例

@Bean
public SecurityManager securityManager(List<Realm> realms) {
    DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    
    ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
    authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
    
    manager.setAuthenticator(authenticator);
    manager.setRealms(realms); // 注入多个Realm
    return manager;
}

典型组合场景

  1. 本地数据库Realm + LDAPRealm
  2. JWTRealm + OAuth2Realm
  3. 主备Realm策略(FirstSuccessfulStrategy)

优先级控制

@Bean
@Order(1)
public Realm primaryRealm() {
    return new PrimaryRealm();
}

@Bean 
@Order(2)
public Realm secondaryRealm() {
    return new SecondaryRealm();
}

最佳实践总结

  1. 配置优化

    • 生产环境务必启用缓存
    • 敏感URL应使用SSL要求配置
  2. 安全建议

    @Bean
    public RememberMeManager rememberMeManager() {
        CookieRememberMeManager manager = new CookieRememberMeManager();
        manager.setCipherKey(Base64.decode("secureKey..."));
        return manager;
    }
  3. 调试技巧

    # application.properties
    logging.level.org.apache.shiro=DEBUG
  4. 扩展方向

    • 实现SessionDAO集成Redis
    • 自定义PermissionResolver支持复杂权限逻辑

通过合理组合这些集成方案,可以构建既安全又灵活的企业级权限系统。

评论已关闭