Spring Boot:配置自定义MethodSecurityExpressionOperations? [英] Spring Boot: Configure custom MethodSecurityExpressionOperations?

查看:441
本文介绍了Spring Boot:配置自定义MethodSecurityExpressionOperations?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在拍摄曾经使用过的spring boot安全性配置时遇到麻烦,但是现在无法识别我的自定义定义。我的目标是在Spring中使用自定义注释通过方法级安全性来保护我们所有的服务。

I am trouble shooting a spring boot security configuration that I once had working, but now is not recognizing my custom definitions. My goal was to protect all of our Services with method level security in Spring with custom annotations.

启动服务时,我的CustomMethodSecurityConfig实例化并调用createExpressionHandler(),但是当我向服务发出请求时,它不会在CustomMethodSecurityExpressionHandler上调用createSecurityExpressionRoot(...),而是在DefaultWebSecurityExpressionHandler上调用。

When I start the service my CustomMethodSecurityConfig is instantiated and does call createExpressionHandler(), but when I make the request to the service it does not call createSecurityExpressionRoot(...) on my CustomMethodSecurityExpressionHandler, but on the DefaultWebSecurityExpressionHandler.

我感谢任何人的见解能够提供为何Spring Security无法识别我在CustomMethodSecurityExpressionRoot中定义的表达式的原因。

I appreciate any insights anyone may be able to provide as to why Spring Security is not recognizing my expressions defined in my CustomMethodSecurityExpressionRoot.

这里是GlobalMethodSecurityConfiguration类的摘要

Here is a snippet of my GlobalMethodSecurityConfiguration class

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomMethodSecurityConfig extends GlobalMethodSecurityConfiguration {

  private final MyService1 myService1;
  private final MyService2 myService2;
  private final MyService3 myService3;

  @Autowired
  public CustomMethodSecurityConfig(MyService1 myService1, MyService2 myService2,
                                    MyService3 myService3) {
    this.myService1 = myService1;
    this.myService2 = myService2;
    this.myService3 = myService3;
  }

  @Override
  protected MethodSecurityExpressionHandler createExpressionHandler() {
    CustomMethodSecurityExpressionHandler expressionHandler =
        new CustomMethodSecurityExpressionHandler(myService1, myService2, myService3);
    expressionHandler.setPermissionEvaluator(permissionEvaluator());
    return expressionHandler;
  }
}

这是我的DefaultMethodSecurityExpressionHandler类的摘要

Here is a snippet of my DefaultMethodSecurityExpressionHandler class

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

  private final MyService1 myService1;
  private final MyService2 myService2;
  private final MyService3 myService3;
  private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();

  public CustomMethodSecurityExpressionHandler(MyService1 myService1, MyService2 myService2,
                                               MyService3 myService3) {
    this.myService1 = myService1;
    this.myService2 = myService2;
    this.myService3 = myService3;
  }

  @Override
  protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
                                                                            MethodInvocation invocation) {
    CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication,
                                                                                     myService1,
                                                                                     myService2,
                                                                                     myService3);

    root.setPermissionEvaluator(getPermissionEvaluator());
    root.setTrustResolver(this.trustResolver);
    root.setRoleHierarchy(getRoleHierarchy());

    return root;
  }
}

这是我的SecurityExpressionRoot的摘录,在这里我正在定义在服务注释中使用的SpEL表达式。我仅包括一个简化的isUser为例。这些方法的作用并不重要,但是它们是可见的事实。

Here is the snippet of my SecurityExpressionRoot, this is where I am defining my SpEL expressions which I use in annotations on my Services. I have only included a simplified, isUser as an example. What these methods do isn't important, but the fact that they are visible.

public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot
    implements MethodSecurityExpressionOperations {

  private Object filterObject;
  private Object returnObject;

  private MyService1 myService1;
  private MyService2 myService2;
  private MyService3 myService3;

  public CustomMethodSecurityExpressionRoot(
      Authentication authentication,
      MyService1 myService1,
      MyService2 myService2,
      MyService3 myService3) {
    super(authentication);
    this.myService1 = myService1;
    this.myService2 = myService2;
    this.myService3 = myService3;
  }

  @Override
  public Object getFilterObject() {
    return this.filterObject;
  }

  @Override
  public Object getReturnObject() {
    return this.returnObject;
  }

  @Override
  public void setFilterObject(Object obj) {
    this.filterObject = obj;
  }

  @Override
  public void setReturnObject(Object obj) {
    this.returnObject = obj;
  }

  @Override
  public Object getThis() {
    return this;
  }

  //All custom SpEL methods
  public boolean isUser(Long userId) {
    SecurityUser user = (SecurityUser) this.getPrincipal();
    return user.getUserId() == userId;
  }

  ...

}

最后,这是我的WebSecurityConfigurerAdapter的一小段,它是串联使用的,它验证了来自我们UAA服务器的外部身份验证令牌。

And finally here is a snippet of my WebSecurityConfigurerAdapter which is used in tandem, it verifies the external authentication token from our UAA server.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    prePostEnabled = true,
    proxyTargetClass = true)
public class ServiceSecurityConfig extends WebSecurityConfigurerAdapter {

  private final TokenCheckService _tokenCheckService;

  @Autowired
  ServiceSecurityConfig(TokenCheckService tokenCheckService) {
    _tokenCheckService = tokenCheckService;
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(new TokenAuthenticationProvider(_tokenCheckService));
  }

  @Override
  public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(HttpMethod.OPTIONS, "/api/**");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
        http
            .anonymous()
              .disable()
            .csrf()
              .disable()
            .exceptionHandling()
              .authenticationEntryPoint(new UnAuthorizedEntryPoint())
              .and()
            .sessionManagement()
              .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
              .and()
            .authorizeRequests()
              .anyRequest().authenticated();
    http.addFilterBefore(new AuthenticationTokenFilter(), BasicAuthenticationFilter.class);
  }
}

编辑:
我认为是我的WebDecisionVoters在初始化期间被覆盖的问题。如果我在肯定构造函数中有一个断点

I seem to think it is an issue with my WebDecisionVoters being overridden during intialization. If I have a breakpoint in the Affirmative constructor

AffirmativeBased(List<AccessDecisionVoter<? extends Object>> decisionVoters)

我可以看到AffirmativeBased实例化了3个决策者,其中之一是PreInvocationAuthorizationAdviceVoter,其中包含对我的引用表达式处理程序。我相信这是由方法SecurityInterceptor的bean实例化创建的。

I can see AffirmativeBased being instantiated with 3 decision voters, one of which is a PreInvocationAuthorizationAdviceVoter, which contains a reference to my expression handler. I believe this is being created by bean instantiation of the methodSecurityInterceptor.

当我继续断点时,我再次命中了相同的基于Affirmative的构造函数,但是只有一个决策投票者,一个WebExperssionVoter,带有对DefaultWebSecurityExpressionHandler实例的引用。我相信这是通过springSecurityFilterChain的bean实例化创建的。

When I continue the breakpoint I again hit the same Affirmative based constructor, but with only one decision voter, a WebExperssionVoter with a reference to an instance of DefaultWebSecurityExpressionHandler. I believe this is being created by bean instantiation of the springSecurityFilterChain.

推荐答案

我能够按照中的步骤解决此问题。 带有服务的自定义SecurityExpression 。问题似乎出在与安全性分离的自动接线服务上。导致问题并删除它们的MyService1,MyService2和MyService3允许安全性起作用。

I was able to resolve this issue by following the steps in Custom SecurityExpression with Service. The issue appears to have been with my autowired services that were separate from security. MyService1, MyService2, and MyService3 causing the issues and removing them allowed security to work.

必须在扩展DefaultMethodSecurityExpressionHandler的类的createSecurityExpressionRoot中设置任何其他服务。

Any additional services must be set in createSecurityExpressionRoot of the class that extends DefaultMethodSecurityExpressionHandler.

@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
    CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
    // Other initialization
    root.setMyService1(applicationContext.getBean(MyService1.class));
    root.setMyService2(applicationContext.getBean(MyService2.class));
    root.setMyService3(applicationContext.getBean(MyService3.class));
    return root;
}

这篇关于Spring Boot:配置自定义MethodSecurityExpressionOperations?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆