【问题标题】:Spring security check if user has access to mentioned urlSpring安全检查用户是否可以访问提到的url
【发布时间】:2017-12-29 19:26:23
【问题描述】:

我已经开始使用 Spring Security,但经过大量研究后,我无法找到答案:

如果我明确想检查用户 A 是否可以访问 B 的内容。我可以使用 JSP 标签支持Spring Security - check if web url is secure / protected 来检查这一点

<sec:authorize url="stuff/B">

但是如果我想在控制器(java 类)中检查相同的东西怎么办。我在这里没有找到任何弹簧功能来检查登录用户是否可以访问提到的 url(https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html)

【问题讨论】:

    标签: java spring spring-mvc spring-security


    【解决方案1】:

    来自javadoc的提示:

    要使用此标记,您的应用程序上下文中还必须有一个 WebInvocationPrivilegeEvaluator 实例。如果您正在使用命名空间,则会自动注册一个。这是DefaultWebInvocationPrivilegeEvaluator 的一个实例,”

    DefaultWebInvocationPrivilegeEvaluator 的javadoc 中,我们可以看到应该可以完成这项工作的isAllowed 方法:

    // privilegeEvaluator is a WebInvocationPrivilegeEvaluator "autowired"
    boolean allowed = privilegeEvaluator.isAllowed("/stuff/B", yourAuthentication);
    

    【讨论】:

      【解决方案2】:

      为什么不使用这样的注解:

      @PreAuthorize("hasRole('ROLE_USER')")
      public void create(Contact contact);
      

      注解是 Spring 3+ 的标准方式

      【讨论】:

        【解决方案3】:

        您正在寻找正确的地方,您附加的链接提到了您需要的东西。由于您希望对控制器进行访问控制并检查每个用户(而不是角色),您可以使用带有“hasPermission”表达式或类似表达式的“@PreAuthorize”注释。

        如果您想自定义解决方案,您可以查看here 了解基于表达式的访问控制,查看here 获取自定义安全表达式示例。

        【讨论】:

          【解决方案4】:

          1) 首先我们需要知道用户是否可以输入 URL。这可以使用 WebInvocationPrivilegeEvaluator 轻松实现。

          privilegeEvaluator.isAllowed(contextPath, url, "GET", currentUser);
          

          2) 现在我们需要识别用户是否可以访问处理程序方法

          private boolean isAllowedByAnnotation(Authentication currentUser, HandlerMethod method) {
              PreInvocationAuthorizationAdvice advice = new ExpressionBasedPreInvocationAdvice();
              PreInvocationAuthorizationAdviceVoter voter = new PreInvocationAuthorizationAdviceVoter(advice);
          
              MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
              PrePostInvocationAttributeFactory factory = new ExpressionBasedAnnotationAttributeFactory(expressionHandler);
              PrePostAnnotationSecurityMetadataSource metadataSource = new PrePostAnnotationSecurityMetadataSource(factory);
          
              Class<?> controller = method.getBeanType();
              MethodInvocation mi = MethodInvocationUtils.createFromClass(controller, method.getMethod().getName());
              Collection<ConfigAttribute> attributes = metadataSource.getAttributes(method.getMethod(), controller);
          
              return PreInvocationAuthorizationAdviceVoter.ACCESS_GRANTED == voter.vote(currentUser, mi, attributes);
          }
          

          【讨论】:

            【解决方案5】:

            我们可以创建一个自定义的 PermissionEvaluator 并使用

            hasPermission(Authentication authentication, Object domainObject, 对象权限)。

              @Override
              protected MethodSecurityExpressionHandler createExpressionHandler() {
                final DefaultMethodSecurityExpressionHandler expressionHandler =
                    new DefaultMethodSecurityExpressionHandler();
                expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
                return expressionHandler;
              }
            
             @Bean
              public aclServiceImpl aclService() {
                final AclServiceImpl mutableAclService = new AclServiceImpl 
                    (authorizationStrategy(), grantingStrategy());
                return mutableAclService;
              }
            

            AclServiceImpl是MutableAclService的实现

            【讨论】:

              【解决方案6】:

              最明显有用的注解是@PreAuthorize,它决定一个方法是否可以被实际调用。例如(来自“联系人”示例应用程序)

              @PreAuthorize("hasRole('USER')")
              public void create(Contact contact);
              

              这意味着只有具有“ROLE_USER”角色的用户才能访问。显然,使用传统配置和所需角色的简单配置属性可以轻松实现相同的目标。但是呢:

              @PreAuthorize("hasPermission(#contact, 'admin')")
              public void deletePermission(Contact contact, Sid recipient, Permission permission);
              

              这里我们实际上使用方法参数作为表达式的一部分来确定当前用户是否具有给定联系人的“管理员”权限。内置的 hasPermission() 表达式通过应用程序上下文链接到 Spring Security ACL 模块。

              更详细的解释请参考Link

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-03-03
                • 1970-01-01
                • 2018-11-18
                • 2013-06-20
                • 2011-10-01
                相关资源
                最近更新 更多