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

问题描述 投票:0回答:7

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

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

    return "[email protected]";
  }

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

    [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。有任何想法吗?

java spring-mvc spring-security oauth-2.0
7个回答
17
投票

要启用

#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 {
  ...
}

5
投票

我想你还需要补充: @EnableGlobalMethodSecurity(prePostEnabled = true) 为了让它工作。

已在不同页面回答


5
投票

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

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

3
投票

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

.hasAuthority("SCOPE_scopename")

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

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


0
投票

我遇到了同样的问题,但仅限于单元测试(

@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)

0
投票

对我来说,这是这个答案

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

这个其他答案

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

0
投票

我也有同样的问题 然后我添加了

@EnableMethodSecurity(securedEnabled = true)  // bootstrap class


// in controller 
@PreAuthorize("hasAuthority('SCOPE_write')")
@GetMapping("/api/users")
public List<?> getUsers() {
    System.err.println("API invoked in Resource Server");
    return of("john", "allen", "Ashley" );
}

它的工作

© www.soinside.com 2019 - 2024. All rights reserved.