如何配置 Spring Security 以允许在 JSP 页面中使用 hasPermission?

Posted

技术标签:

【中文标题】如何配置 Spring Security 以允许在 JSP 页面中使用 hasPermission?【英文标题】:How configure the Spring Security to allow the use for hasPermission in the JSP page? 【发布时间】:2014-07-21 09:55:30 【问题描述】:

我正在尝试在我的 spring 项目的 jsp 页面中使用 hasPermission。我已经在我的控制器/服务类的方法中毫无问题地使用它。阅读文章:

http://docs.spring.io/spring-security/site/docs/4.0.0.M1/reference/htmlsingle/#the-accesscontrollist-tag

从官方文档中,我了解到为此我需要实现一个派生自 DefaultPermission 的类,该类将从自定义 AclService 类中加载。

我的问题是我找不到有关如何实现所有这些类的任何信息,甚至不知道这种方法是否是唯一的方法,或者我是否以正确的方式理解了该主题(官方文档非常简短关于这个主题,在互联网的其余部分我找不到更多信息)。

任何人都可以在这里指出正确的方向吗?可能会指出一些教程或代码示例。

更新

从 *** 阅读其他主题,我发现了这个建议:

This is what I have done. I created my own permission evaulator:
>     public class MyPermissionEvaluator implements PermissionEvaluator 
>     ...
>     
Then I configured spring to use that evaulator via
>     <beans:bean id="expressionHandler"
>         class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
>           <beans:property name="permissionEvaluator" ref="permissionEvaluator"/>
>     </beans:bean>
>     
>     <beans:bean id="webExpressionHandler" 
>         class="com.bulb.learn.webapp.security.CustomWebSecurityExpressionHandler">
>         <beans:property name="permissionEvaluator" ref="permissionEvaluator"/>
>     </beans:bean>
>     
>     <beans:bean id="permissionEvaluator" class="my.domain.MyPermissionEvaluator" />
That way all expression handlers have access to my evaulator.

Then, in JSP (actually, I am using jspx), I can make tags like this:
>     <sec:authorize access="hasPermission(#childUnit, 'read')">
>          ...
>     </sec:authorize>
Hope that gets you heading in the right direction.

因为我已经有一个自定义 PermissionEvaluator,所以我尝试了这个方法。它部分工作,但现在,即使用户拥有权限,标签内的元素也不会显示。此外,尽管应用程序的构建和执行没有错误,但 Eclipse 会指示与此标记相关的错误(“令牌上的语法错误,错误的构造”)。

在控制台中,显示此错误:

un 03, 2014 7:48:40 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'cadastra_usuario' on object null
Jun 03, 2014 7:48:40 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'altera_usuario' on object null
Jun 03, 2014 7:48:40 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'remove_usuario' on object null
Jun 03, 2014 7:48:45 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'cadastra_permissao' on object null
Jun 03, 2014 7:48:45 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'altera_permissao' on object null
Jun 03, 2014 7:48:45 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'remove_permissao' on object null
Jun 03, 2014 7:48:57 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'cadastra_usuario' on object null
Jun 03, 2014 7:48:57 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'altera_usuario' on object null
Jun 03, 2014 7:48:57 PM org.springframework.security.access.expression.DenyAllPermissionEvaluator hasPermission
Advertência: Denying user klebermo permission 'remove_usuario' on object null

在互联网上,我发现一些文章建议我应该为 WebSecurityExpressionHandler 实现一个接口。

有人知道这里的正确步骤是什么吗?

更新 2

以前,我使用的是这个标签:

<sec:accesscontrollist hasPermission="1,2" domainObject="$someObject">

如果用户对给定对象具有值“1”或“2”所代表的权限,则会显示此信息。

</sec:accesscontrollist>

在控制台中没有显示错误,但仍然无法正常工作。我的问题是我需要实现哪个对象来归属标签的 domainObject?

【问题讨论】:

@see docs.spring.io/spring-security/site/docs/4.0.0.M1/reference/… JSP 标记库 例如 此内容仅对列表中具有“主管”权限的用户可见GrantedAuthority 我的代码中已经有了这个标签,按照链接中的说明(我已经看过)。而且我不想使用hasRole,而是hasPermission:我的应用程序中有角色和权限(每个Role可以有多个Permissions,用户可以创建新的Roles来关联需要关联的Permissions)。 看看krams915.blogspot.com/2011/01/…和这个Q。***.com/questions/7481869/… 我的项目中有这个类 PermissionEvaluator,我在我的方法(在控制器和服务类中)使用带有参数 hasPermission 的注释 @PreAuthorize。但我无法在我的 JSP 页面中使用。在这里查看我的配置:github.com/klebermo/lojavirtual/tree/master/src/main/java/com/… 【参考方案1】:

您的CustomPermissionEvaluator 未被调用。

在您的 SecurityConfig.java 中尝试以下代码。

...
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;

...
public class SecurityConfig extends WebSecurityConfigurerAdapter 
  ...

  @Override
  public void configure(WebSecurity web) throws Exception 
    DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
    handler.setPermissionEvaluator(new CustomPermissionEvaluator());
    web.expressionHandler(handler);
  

WebApplicationInitializer

...
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

...
public class AnnotationConfigDispatcherServletInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer 

  @Override
  protected Class<?>[] getRootConfigClasses() 
    return new Class[] 
      SecurityConfig.class,
    ;
  

【讨论】:

我怎样才能确保configure(WebSecurity web) 在启动时被调用,或者有没有办法在纯XML 中执行您在此处显示的内容?就像将我的 CustomPermissionEvaluator 注入到 WebSecurity bean 中一样? 您可以使用AbstractAnnotationConfigDispatcherServletInitializer 确保configure(WebSecurity web) 在启动时被调用。我已经编辑了我的答案。【参考方案2】:
<sec:accesscontrollist hasPermission="1,2" domainObject="$someObject">

someObject 表示应该应用 acl 的对象。所以在你的情况下childUnit bean。

仅供参考,我做了类似的事情,但没有使用 acl,我们连接了 parameternamediscoverer。

【讨论】:

我还没有 bean childUnit,这只是我找到的示例。我尝试在我的应用程序中实现相同的功能,但我遇到了上面描述的问题(第一次更新)。你知道我应该在哪里实现这个childUnit bean吗?顺便说一句,但是你的例子看起来也很不错。我会试一试的。 childunit 是您想要保护访问的任何示例......在您的情况下,无论您的 jsp 中访问的是什么 bean。普通角色安全允许按角色设置权限,无论使用 acl 都允许系统中的每个项目具有不同的安全访问权限(如果可以的话,尽量避免它 - 还没有看到需要这样做的业务案例(并且实际上在很长一段时间内使用学期))。我们做了一个,但没有人会为更新列表而烦恼。【参考方案3】:

就我而言,我在 httpsession 中有一些字符串的 ArrayList。我需要向用户显示一个按钮,只有当按钮功能名称在该列表中可用时。我已经通过 Spring Security ACL 实现了它。

为此在类路径中添加 ACL + spring security core jar。

<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>$spring.security.version</version>
    </dependency>       
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>$spring.security.version</version>
    </dependency>       
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-acl</artifactId>
        <version>$spring.security.version</version>
    </dependency>

然后,我在 xml 中添加了 bean。

<global-method-security pre-post-annotations="enabled">
  <expression-handler ref="expressionHandler"/>
</global-method-security>    
<beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <beans:property name="permissionEvaluator" ref="permissionEvaluator"/>
</beans:bean> 
<beans:bean id="permissionEvaluator" class="com.config.BasePermissionEvaluator"/>

然后是处理程序类BasePermissionEvaluator,这个类将评估,如果那个按钮有权限,

public class BasePermissionEvaluator implements PermissionEvaluator
 @Override
 public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) 

  boolean hasPermission = true;
  // targetDomainObject [101001, 102001, 103001, 201001, 202001, 203001, 204001, 205001, 206001, 301001, 302001, 303001]permission : 303001
    @SuppressWarnings("unchecked")
    List<String> functionList =(List<String>) targetDomainObject;       
    if(!functionList.contains(permission.toString())) 
        hasPermission = false;  
    
  return hasPermission;
 

 @Override
 public boolean hasPermission(Authentication authentication,
   Serializable targetId, String targetType, Object permission) 
    throw new RuntimeException("Id and Class permissions are not supperted by this application");
 

终于在jsp中,

    <%@taglib uri="http://www.springframework.org/security/tags"
 prefix="sec"%>

<sec:accesscontrollist hasPermission="101001"   domainObject="$USER_FUNCTIONS"> 
                    <button type="reset" id ="clearMPId"><spring:message code="mp.clear"/></button>
  </sec:accesscontrollist>   

希望对你有帮助。

【讨论】:

以上是关于如何配置 Spring Security 以允许在 JSP 页面中使用 hasPermission?的主要内容,如果未能解决你的问题,请参考以下文章

配置Spring Security以使用两个不同的登录页面

如何使用 spring-security-saml2 配置服务提供者以使用 EncryptedAssertions?

如何在 Spring Security 中配置资源服务器以使用 JWT 令牌中的附加信息

Spring security - 允许导航但保护某些页面

如何配置 Spring Boot 和 Spring Security 以支持表单登录和 Google OAuth2 登录

如何在spring security中为来自两个不同表的不同用户配置身份验证?