java #oauth2 方法级别的安全表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29797721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 15:57:32  来源:igfitidea点击:

#oauth2 security expressions on method level

javaspring-mvcspring-securityoauth-2.0

提问by Marek R

What should I do to be able to use #oauth2 security expressions on method level like on the example below?

我应该怎么做才能在方法级别使用 #oauth2 安全表达式,如下例所示?

@RequestMapping(value = "email", method = RequestMethod.GET)
  @ResponseBody
  @PreAuthorize("#oauth2.hasScope('read')")
  public String email() {

    return "[email protected]";
  }

If I do a request to that resource I receive

如果我向该资源发出请求,我会收到

    [INFO] java.lang.IllegalArgumentException: Failed to evaluate expression '#oauth2.hasScope('read')'
[INFO]  at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:14)
[INFO]  at org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice.before(ExpressionBasedPreInvocationAdvice.java:44)
[INFO]  at org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter.vote(PreInvocationAuthorizationAdviceVoter.java:57)
[INFO]  at org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter.vote(PreInvocationAuthorizationAdviceVoter.java:25)
[INFO]  at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:62)
[INFO]  at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232)
[INFO]  at org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor.invoke(AspectJMethodSecurityInterceptor.java:43)
[INFO]  at org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect.ajc$around$org_springframework_security_access_intercept_aspectj_aspect_AnnotationSecurityAspect$c4d57a2b(AnnotationSecurityAspect.aj:63)
[INFO]  at pl.insert.controllers.ResourceController.email(ResourceController.java:22)

The same thing works well if I specify the access in my ResourceServerConfiguration instead of @Controllers' methods

如果我在 ResourceServerConfiguration 中指定访问而不是 @Controllers 的方法,同样的事情会很好地工作

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

  @Override
  public void configure(HttpSecurity http) throws Exception {
    http.requestMatchers().antMatchers("/oauth/resources/**");
    http.authorizeRequests().anyRequest().access("#oauth2.hasScope('read')");
  }
}

Standard security expressions like @PreAuthorize("permitAll") or @PreAuthorize("denyAll") work as expected. So, probably I have to tell somehow to my AspectJMethodSecurityInterceptor to use OAuth2WebSecurityExpressionHandler. Any ideas?

像@PreAuthorize("permitAll") 或@PreAuthorize("denyAll") 这样的标准安全表达式按预期工作。所以,可能我必须以某种方式告诉我的 AspectJMethodSecurityInterceptor 使用 OAuth2WebSecurityExpressionHandler。有任何想法吗?

回答by Marek R

To enable #oAuth2 security expressions it is only needed to set default expression handler as OAuth2MethodSecurityExpressionHandler instead of DefaultMethodSecurityExpressionHandler. Because OAuth2MethodSecurityExpressionHandler extends it anyway then the whole previous functionality remains the same. I my configuration I use both GlobalMethodSecurityConfiguration and WebSecurityConfigurerAdapter.

要启用#oAuth2 安全表达式,只需将默认表达式处理程序设置为 OAuth2MethodSecurityExpressionHandler 而不是 DefaultMethodSecurityExpressionHandler。因为 OAuth2MethodSecurityExpressionHandler 无论如何都会扩展它,所以之前的整个功能保持不变。我的配置同时使用 GlobalMethodSecurityConfiguration 和 WebSecurityConfigurerAdapter。

@Configuration
@EnableGlobalMethodSecurity
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

  @Override
  protected MethodSecurityExpressionHandler createExpressionHandler() {
    return new OAuth2MethodSecurityExpressionHandler();
  }
}

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  ...
}


@Configuration
@Import({ SecurityConfiguration.class, MethodSecurityConfiguration.class })
public class AppConfiguration {
  ...
}

回答by JohanB

A simpler solution would be to let Spring Boot autoconfigure. Adding the following dependency solved this for me:

一个更简单的解决方案是让 Spring Boot 自动配置。添加以下依赖项为我解决了这个问题:

compile('org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.0.4.RELEASE')

回答by thygesen

I think you also need to add: @EnableGlobalMethodSecurity(prePostEnabled = true) in order to get it to work.

我认为您还需要添加:@EnableGlobalMethodSecurity( prePostEnabled = true) 才能使其正常工作。

Answered on deferent page

在不同的页面上回答

回答by Wim Deblauwe

I had the same problem, but only in a unit test (@WebMvcTest). I had to add @EnableGlobalMethodSecurityon the inner class that defined the configuration for the test:

我遇到了同样的问题,但仅在单元测试 ( @WebMvcTest) 中。我必须添加@EnableGlobalMethodSecurity定义测试配置的内部类:

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTest {

  @TestConfiguration
  @Import({HymansonCustomizations.class,SecuritySettings.class,
        OAuth2ServerConfiguration.class, WebSecurityConfiguration.class,
        TokenGrantersConfiguration.class})
  @EnableGlobalMethodSecurity
  public static class TestConfig {
  }
}

UPDATE: In Spring Boot 2.x, you might get:

更新:在 Spring Boot 2.x 中,您可能会得到:

java.lang.IllegalStateException: In the composition of all global method configuration, no annotation support was actually activated

java.lang.IllegalStateException: 在所有全局方法配置的组合中,实际上并没有激活注解支持

The reason is that you added @EnableGlobalMethodSecuritywithout actually enabling anything. To fix it, set at least one of the properties of the annotation to true. E.g:

原因是您在@EnableGlobalMethodSecurity没有实际启用任何内容的情况下添加了内容。要修复它,请将注释的至少一个属性设置为 true。例如:

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)