Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何创建用于spring安全表达式语言注释的自定义方法_Java_Spring_Spring Security - Fatal编程技术网

Java 如何创建用于spring安全表达式语言注释的自定义方法

Java 如何创建用于spring安全表达式语言注释的自定义方法,java,spring,spring-security,Java,Spring,Spring Security,我想创建一个类,该类添加了在spring安全表达式语言中使用的自定义方法,用于通过注释进行基于方法的授权 例如,我想创建一个自定义方法,如“customMethodReturningBoolean”,以如下方式使用: @PreAuthorize("customMethodReturningBoolean()") public void myMethodToSecure() { // whatever } @Component("mySecurityService") pu

我想创建一个类,该类添加了在spring安全表达式语言中使用的自定义方法,用于通过注释进行基于方法的授权

例如,我想创建一个自定义方法,如“customMethodReturningBoolean”,以如下方式使用:

  @PreAuthorize("customMethodReturningBoolean()")
  public void myMethodToSecure() { 
    // whatever
  }
@Component("mySecurityService")
public class MySecurityService {
    public boolean hasPermission(String key) {
        return true;
    }
}
我的问题是。
如果可能的话,我应该创建一个子类来创建我的自定义方法,我应该如何在SpringXML配置文件中配置它,然后有人给我一个这样使用的自定义方法的示例?

您将需要对两个类进行子类化

首先,设置一个新的方法表达式处理程序

<global-method-security>
  <expression-handler ref="myMethodSecurityExpressionHandler"/>
</global-method-security>
谢谢,但它不起作用有几个原因:

DefaultMethodSecurityExpressionHandler的属性是私有反射可见性模糊集 至少在Eclipse中,我无法解析MethodSecurityEvaluationContext对象 区别在于我们调用现有方法,然后添加自定义根对象。最后,我刚刚返回了一个对象类型,因为MethodSecurityEvaluationContext不会在编译器中解析它们都来自同一接口。这是我现在在生产中使用的代码

使用我们的自定义根目录:

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler  {

    // parent constructor
    public CustomMethodSecurityExpressionHandler() {
        super();
    }

    /**
     * Custom override to use {@link CustomSecurityExpressionRoot}
     * 
     * Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
     * configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object.
     */
    @Override
    public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
        // due to private methods, call original method, then override it's root with ours
        StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
        ctx.setRootObject( new CustomSecurityExpressionRoot(auth) );
        return ctx;
    }
}
最后更新securityContext.xml,并确保它是从applcationContext.xml引用的:

<!-- setup method level security using annotations -->
<security:global-method-security
        jsr250-annotations="disabled"
        secured-annotations="disabled"
        pre-post-annotations="enabled">
    <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<!--<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">-->
<bean id="expressionHandler" class="com.yourSite.security.CustomMethodSecurityExpressionHandler" />

注意:@Secured注释将不接受此重写,因为它通过不同的验证处理程序运行。因此,在上面的xml中,我禁用了它们以防止以后的混淆。

上述技术都不再有效。似乎Spring已经竭尽全力阻止用户重写SecurityExpressionRoot

编辑11/19/14设置弹簧以使用安全注释:

<beans ... xmlns:sec="http://www.springframework.org/schema/security" ... >
...
<sec:global-method-security pre-post-annotations="enabled" />
然后在jsp中执行以下操作:

<sec:authorize access="@mySecurityService.hasPermission('special')">
    <input type="button" value="Special Button" />
</sec:authorize>
此外,您可以在@PreAuthorize注释中使用来访问当前身份验证以及方法参数

例如:

@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
    MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);
    MethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(auth);
    root.setTrustResolver(trustResolver);
    root.setPermissionEvaluator(permissionEvaluator);
    root.setRoleHierarchy(roleHierarchy);
    ctx.setRootObject(root);

    return ctx;
}
@Component("mySecurityService")
public class MySecurityService {
    public boolean hasPermission(Authentication authentication, String foo) { ... }
}
然后更新@PreAuthorize以匹配新方法签名:

@PreAuthorize("@mySecurityService.hasPermission(authentication, #foo)")
public void doSpecialStuff(String foo) { ... }

嗯,听起来是个好主意,但是DefaultMethodSecurityExpressionHandler的所有属性都是私有的,没有访问器,所以我很好奇你是如何扩展这个类而没有任何丑陋的反射的。谢谢。你是说信任分解器等?至少在Spring Security 3.0中,这些都在DefaultMethodSecurityExpressionHandler中有setter。请参见:@ericacm如何避免MethodSecurityExpressionRoot被包私有化?@Bosh在hasPermission方法中,可以使用Authentication=SecurityContextHolder.getContext.getAuthentication;获取当前身份验证令牌。感谢James的回答。我必须在spring配置文件中定义mySecurityService吗?如果您有服务所在包的组件扫描设置,则不需要在任何XML文件中定义mySecurityService。如果没有匹配的组件扫描,那么必须使用XMLBean定义@预授权来自org.springframework.security您可能需要像下面这样为注释指定bean的名称:@ComponentmySecurityService或使用@Named注释。@VJS请查看我所做的编辑。您需要配置spring以使用这些注释。我很惊讶没有人抱怨这个重要的遗漏细节:我现在没有时间键入答案,但我遵循了这个指南,它运行得非常出色:我使用的是SpringSecurity 5.1.1。
@Component("mySecurityService")
public class MySecurityService {
    public boolean hasPermission(Authentication authentication, String foo) { ... }
}
@PreAuthorize("@mySecurityService.hasPermission(authentication, #foo)")
public void doSpecialStuff(String foo) { ... }