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

Posted

技术标签:

【中文标题】#oauth2 方法级别的安全表达式【英文标题】:#oauth2 security expressions on method level 【发布时间】:2015-06-30 02:53:05 【问题描述】:

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

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

    return "test@email.com";
  

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

    [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$1$c4d57a2b(AnnotationSecurityAspect.aj:63)
[INFO]  at pl.insert.controllers.ResourceController.email(ResourceController.java:22)

如果我在我的 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')");
  

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

【问题讨论】:

嗨@Marek!您找到解决问题的方法了吗?同样的问题... 不幸的是,没有,据我记得我花了一些时间来解决这个问题,但解决方案太复杂了,最终不值得实​​施。我使用@Configuration 手动执行此操作:( 就我而言,这并不那么痛苦,但我可以想象在某些情况下可能会这样。 好的,谢谢你的回答 我刚刚在这里提交了一个问题:github.com/spring-projects/spring-boot/issues/3910 @SébastienNussbaumer 检查下面的答案。我刚刚通过解决另一个问题找到了解决方案。它对我来说很好。 【参考方案1】:

要启用#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 
  ...

【讨论】:

我也有同样的问题。试过这个,但没有帮助。有人可以分享一些源代码吗? “没有帮助”是什么意思?是否已加载 @Configuration 类并调用过 createExpressionHandler() 方法?如果您的 AspectJMethodSecurityInterceptor 确实使用 OAuth2MethodSecurityExpressionHandler,则在调试器中检查“是”。如果“否”,请调查原因。 将覆盖添加到createExpressionHandler 对我来说很好。声称您可以添加 spring-security-oauth2-autoconfigure 依赖项的其他解决方案对我不起作用(至少在我的单元测试中没有,没有检查我的应用程序本身)。【参考方案2】:

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

Answered on deferent page

【讨论】:

【参考方案3】:

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

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

【讨论】:

我不得不删除与 GlobalMethodSecurityConfiguration 类相关的配置,然后我添加了这个依赖然后它就起作用了。【参考方案4】:

这是一个老问题,事情已经改变了。使用 Spring Security 5 应该使用:

.hasAuthority("SCOPE_scopename")

Spring 根据从提供者收到的范围为主体添加权限,前缀为“SCOPE_”。

更多信息:https://www.baeldung.com/spring-security-openid-connect

【讨论】:

【参考方案5】:

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

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

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

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

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

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

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)

【讨论】:

【参考方案6】:

对我来说,是this answer的组合

// spring configuration class annotation
@EnableGlobalMethodSecurity(prePostEnabled = true)

和this other answer

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

【讨论】:

以上是关于#oauth2 方法级别的安全表达式的主要内容,如果未能解决你的问题,请参考以下文章

ASP .NET MVC在每个字段级别禁用客户端验证

OAuth2 全局方法安全

Java SSM 项目实战 day08 方法级别的权限操作 服务器端的权限控制(JSR-250注解)(支持表达式的注解)(@Secured)以及页面端的权限控制

Spring Security:全局方法安全性不起作用

nginx之location匹配优先级和安全问题

spring boot(1.3)基于oauth2资源服务器:不能使用@PreAuthorize方法安全