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

时间:2014-05-31 22:12:14

标签: spring jsp spring-mvc spring-security acl

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

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

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

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

任何人都可以指出我在正确的方向吗?也许指出一些教程或代码示例。

更新

从StackOverflow这里阅读其他主题,我发现了这个消息:

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?

3 个答案:

答案 0 :(得分:7)

您的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,
    };
  }
}

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

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

为此在类路径中添加ACL + spring安全核心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>   

希望它有所帮助。