使用 Apache Shiro 的 Spring Boot

Posted

技术标签:

【中文标题】使用 Apache Shiro 的 Spring Boot【英文标题】:Spring Boot with Apache Shiro 【发布时间】:2015-03-05 14:08:28 【问题描述】:

我目前正在尝试将 Apache Shiro 集成到我的 Spring Boot RESTful API,但遇到了一些问题,想知道是否有人可以提供帮助。

我的 Application.class:

@Configuration
@EnableTransactionManagement
@EnableAutoConfiguration
@ComponentScan(basePackages = "org.xelamitchell.sophia.server")
public class Application 

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    


我的 WebConfig.class:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter 

    @Bean
    public DispatcherServlet dispatcherServlet() 

        DispatcherServlet servlet = new DispatcherServlet();
        servlet.setDispatchOptionsRequest(true);

        return servlet;
    

    @Bean
    public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) 

        ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
        registration.addUrlMappings("/sophia/*");

        return registration;
    

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) 

        Map<String, MediaType> types = new HashMap<>();
        types.put("json", APPLICATION_JSON);
        types.put("xml", APPLICATION_XML);

        configurer
            .defaultContentType(APPLICATION_JSON)
            .mediaTypes(types);

    

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) 

        converters.add(jackson());
        converters.add(jaxb());

        super.configureMessageConverters(converters);
    

    @Bean
    public MappingJackson2HttpMessageConverter jackson() 

        final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.getObjectMapper()
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        return converter;
    

    @Bean
    public Jaxb2RootElementHttpMessageConverter jaxb() 

        final Jaxb2RootElementHttpMessageConverter converter = new Jaxb2RootElementHttpMessageConverter();

        return converter;
    

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter() 

        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setLoginUrl("/sophia/*");
        shiroFilter.setSecurityManager(securityManager());

        Map<String, Filter> filters = new HashMap<>();
        filters.put("anon", new FormAuthenticationFilter());
        filters.put("authc", new FormAuthenticationFilter());
        shiroFilter.setFilters(filters);

        return shiroFilter;
    

    @Bean
    public org.apache.shiro.mgt.SecurityManager securityManager() 

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(sophiaRealm());

        return securityManager;
    

    @Bean(name = "sophiaRealm")
    @DependsOn("lifecycleBeanPostProcessor")
    public SophiaRealm sophiaRealm() 
        return new SophiaRealm();
    

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() 
        return new LifecycleBeanPostProcessor();
    


应用程序启动正常,日志显示正在设置 shiroFilter:

INFO 12:44:44:271 org.springframework.boot.context.embedded.ServletRegistrationBean - Mapping servlet: 'dispatcherServlet' to [/sophia/*] INFO 12:44:44:277 org.springframework.boot.context.embedded.FilterRegistrationBean - Mapping filter: 'shiroFilter' to: [/*]

但是当我尝试访问 /sophia/users 时,我没有被要求进行身份验证,服务器只是给了我响应。

我的 shiroFilter 配置基于这个问题:How to configure Shiro with Spring Boot

【问题讨论】:

快速更新:经过进一步调查,看起来 Shiro 实际上在后台工作。在 sophia/users 方法中,我检查主题是否已登录,如果没有,我使用有效的用户名和密码调用 SecurityUtils.getSubject().login,并且正在根据我的服务检查用户。将过滤器正确注册到我的 servlet 似乎是一个问题。非常感谢任何帮助,因为我已经看了几天了,不知道为什么它没有弹出登录表单或通知 403 Forbidden。 【参考方案1】:

对 shiroFilter 的小改动解决了这个问题:

    删除 shiroFilter.setLoginUrl(String) 使用以下过滤器链定义映射:

Map<String, Filter> filters = new HashMap<>();
filters.put("/**", "authcBasic");
shiroFilter.setFilters(filters);

神奇的是,整个 API 都通过基本 HTTP 身份验证得到保护。 :)

使用Shiro's Default Web Filters

【讨论】:

以上不太对。您需要 setFilterChainDefinitionMap 方法。不是setFilters。即Map&lt;String, String&gt; filterChain = new HashMap&lt;&gt;(); filterChain.put("/**", "authcBasic"); shiroFilter.setFilterChainDefinitionMap(filterChain);。然后它对我来说很好。

以上是关于使用 Apache Shiro 的 Spring Boot的主要内容,如果未能解决你的问题,请参考以下文章

Apache shiro的简单介绍与使用(与spring整合使用)

Apache Shiro 与 Spring Security

使用 Apache Shiro 的 Spring Boot

apache-shiro 的怪事通过 spring-boot 集成到 spring-mvc 中

将 apache Shiro 与 Spring MVC 非 xml 项目一起使用

在Spring MVC中使用Apache Shiro安全框架