【问题标题】:How to perform RunAs using method security with Spring MVC 3.2 and Spring Security 3.1如何使用 Spring MVC 3.2 和 Spring Security 3.1 的方法安全性执行 RunAs
【发布时间】:2013-09-21 23:26:57
【问题描述】:

我有一个带有 Spring MVC 3.2 和 Spring Security 3.1 的 Web 应用程序

我正在使用基于角色的安全性,并已实现 UserDetailsS​​ervice 和 UserDetails 以提供 GrantedAuthority。

我已经使用 jsr250-annotations 启用了全局方法安全性

到目前为止,一切都按预期工作,登录的用户方法访问权限仅限于声明的角色。

我还有一个进一步的要求,即作为具有“系统角色”的特殊用户运行在应用程序初始化期间调用的某些方法,理想情况下是按照 JavaEE RunAs 的方式运行。 我不确定如何在 Spring Security 中执行此操作。

我是否应该尝试创建一个PreAuthenticatedAuthenticationToken,其中包含一些虚构的值和“系统角色”权限。
然后我可以做类似SecurityContextHolder.getContext().setAuthentication(token); 初始化应用程序时。

或者,我应该尝试使用 RunAsManager。这听起来像是我需要的,但我还没有找到任何可以实际使用它的简单示例。

我对 Spring Security 还很陌生,我不确定最好的方法。

【问题讨论】:

    标签: spring spring-mvc spring-security


    【解决方案1】:

    当我的应用程序启动时

    • 我在我的 spring bean 中运行一个后构造方法来在内存中创建一个具有系统角色的特殊用户。
    • 此用户对象实现
      org.springframework.security.core.userdetails.UserDetails
      接口。
    • 然后我使用用户创建一个安全令牌
      org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
    • 然后在安全上下文中设置令牌。

      @Service
      @Transactional(readOnly = true)
      public class ApplicationConfiguration{
          @Inject
          MyService myService;
          @PostConstruct
          @Transactional(readOnly = false)
          public void init(){
      
              // ######## Application Starting #######"
      
              // Create a user that meets the contract of the Spring UserDetails interface
      
              UserAccountImpl sysAcc = new UserAccountImpl("system", "system", "system");
              UserRole role = new UserRole(Role.SYSTEM_ROLE);
              role.addUserPermission(Permission.SYSTEM);
              sysAcc.addUserRole(role);
              UserDetailsAdapter userDetails = new UserDetailsAdapter(sysAcc);
      
              // Create a token and set the security context
      
              PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken( userDetails, userDetails.getPassword(), userDetails.getAuthorities());
              SecurityContextHolder.getContext().setAuthentication(token);
      
              // Now call service method with roles allowed  
      
              myService.initialiseSystem();
          }
      }
      

      ....

      public interface MyService {
          @RolesAllowed(SYSTEM)
          public void initialiseSystem();
      }
      

    【讨论】:

      【解决方案2】:

      您真的需要在上述应用初始化中附加一个角色吗?为什么不像这样提取需要在初始化期间运行的代码:

      public interface Service {
      
          @Secured("hasRole('USER')")
          void service();
      }
      
      public class DefaultService implements Service {
      
          @Override
          public void service() {
              doService();
          }
      
          public void doService() {
              // Implementation here
          }
      }
      
      ...
      
      public class AppInitializer {
      
          @Autowired
          private DefaultService service;
      
          public void init() {
              service.doService();
          }
      }
      

      【讨论】:

      • 最初这种方法看起来不错,但如果 DefaultService 需要自动装配其他 bean,那么我需要使用基于类的注入来自动装配它们,因为它们的接口会有自己的安全注释。这会导致代理和事务支持出现问题,请参阅section 5 Proxied Beans
      【解决方案3】:

      我相信在这种情况下,对您来说一个好的解决方案是使用 Spring Security OAuth,因为它允许您更好地集成到自定义规则以通过令牌进行访问。

      http://projects.spring.io/spring-security-oauth/

      【讨论】:

        猜你喜欢
        • 2013-10-21
        • 2011-10-04
        • 2018-08-05
        • 2015-02-15
        • 2012-03-06
        • 2012-02-17
        • 2014-01-02
        • 2021-12-15
        • 2017-05-15
        相关资源
        最近更新 更多