【问题标题】:Spring 4 MVC + Apache ShiroSpring 4 MVC + Apache Shiro
【发布时间】:2016-07-30 05:29:04
【问题描述】:

我有一个 Spring 4 MVC 应用程序,它对所有端点使用 @RestController 注释。该应用程序不使用web.xmlapplicationContext.xml 文件。一切正常,现在我正试图让 Apache Shiro 与其他一切合作。

希望做的是让 Shiro 在访问我构建的任何 REST 服务时出现 authc/authz 问题时抛出异常。

到目前为止,我已经能够设置一个用于初始化 Shiro 的基本类:

@Configuration
public class ShiroInitializer {

  @Bean(name = "realmLocal")
  @DependsOn ("lifecycleBeanPostProcessor")
  public Realm realmLocal() {
    return new AuthorizingRealm() {
      @Override
      protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
      }

      @Override
      protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        return null;
      }
    };
  }

  @Bean (name = "lifecycleBeanPostProcessor")
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }

  @Bean
  public org.apache.shiro.mgt.SecurityManager getSecurityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(realmLocal());
    return securityManager;
  }

  @DependsOn("lifecycleBeanPostProcessor")
  @Bean
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
    proxyCreator.setProxyTargetClass(true);
    return proxyCreator;
  }

  // enable shiro annotations
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(getSecurityManager());
    return advisor;
  }

  @Bean (name = "shiroFilter")
  public ShiroFilterFactoryBean getShiroFilter() {
    ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
    shiroFilter.setSecurityManager(getSecurityManager());

    Map<String, String> filters = new ConcurrentHashMap<>();
    filters.put("/**", "authcBasic");
    shiroFilter.setFilterChainDefinitionMap(filters);

    return shiroFilter;
  }
}

当我使用 @RequiresUser 构建这样的端点并在初始化程序中的 AuthorizingRealm 中设置断点时,似乎没有任何反应,并且消息显示没有启动任何 authc/authz 功能:

@RestController
@RequestMapping (value = "/")
@RequiresUser
public class RootEndpoint {

  @RequestMapping (method = RequestMethod.GET)
  public String doGet() throws Exception {
    return "{ \"hello\": \"world\" }";
  }
}

这是我的问题

  1. Q1 我的配置中缺少什么?请记住,如果可能,我会尽量避免使用 XML 配置。
  2. Q2 掌握了基础知识后,我可以用什么来抛出异常而不是将用户重定向到另一个页面?我需要自己的自定义 ShiroFilterFactoryBean 吗?

【问题讨论】:

    标签: spring-mvc shiro spring-4


    【解决方案1】:

    我能够通过实际切换到 Spring Boot 来使其工作,这是代码所有者最近允许我这样做的。我终于完成了一个 Shiro 的配置类,如下所示:

    @Configuration
    public class ShiroConfiguration {
    
      @Bean
      public ShiroFilterFactoryBean getShiroFilter() {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(getSecurityManager());
        return factoryBean;
      }
    
      @Bean (name = "securityManager")
      public DefaultWebSecurityManager getSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(getLocaleRealm());
        securityManager.setSessionManager(getSessionManager());
        return securityManager;
      }
    
      @Bean
      public DefaultWebSessionManager getSessionManager() {
        final DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(43200000);
        return sessionManager;
      }
    
      @Bean (name = "localRealm")
      @DependsOn ("lifecycleBeanPostProcessor")
      public LocalRealm getLocaleRealm() {
        return new LocalRealm();
      }
    
      @Bean (name = "lifecycleBeanPostProcessor")
      public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
      }
    
      @Bean
      public MethodInvokingFactoryBean getMethodInvokingFactoryBean() {
        MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean();
        factoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        factoryBean.setArguments(new Object[]{getSecurityManager()});
        return factoryBean;
      }
    }
    

    我还添加了一个自定义处理程序来使用异常和自定义返回数据,方法是添加一个 @ControllerAdvice 实现,其中包含:

    @ExceptionHandler ({
      AuthenticationException.class,
      UnknownAccountException.class,
      UnauthenticatedException.class,
      IncorrectCredentialsException.class,
      UnauthorizedException.class}
    )
    @ResponseStatus (value = HttpStatus.UNAUTHORIZED)
    @ResponseBody
    public RestApiErrorResponse handleUnauthorized() {
      return build(HttpStatus.UNAUTHORIZED);
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-31
      • 2015-09-18
      • 2012-03-08
      • 2017-11-24
      • 2011-07-20
      • 2016-12-17
      • 2017-01-05
      • 2015-10-03
      • 2016-04-08
      相关资源
      最近更新 更多