如何使用Azure AD B2C保护Spring Boot REST API?

4

我正在使用Spring Boot 2.2.0版本和azure-active-directory-b2c-spring-boot-starter 2.2.0版本。 我已经按照其教程保护了一个Thymeleaf网页。 现在,我想要一个REST API以相同的方式进行安全保护,因为实际应用程序将是一个调用我Spring Boot后端的移动应用程序。

我已经弄清楚如何使用密码授权流获得令牌:

POST https://<my-tenant-id>.b2clogin.com/<my-tenant-id.onmicrosoft.com/oauth2/v2.0/token?p=B2C_1_<my-custom-policy>

(使用用户名和密码作为参数)

因此,移动应用程序可以使用该调用。但是,我应该如何配置我的Spring Boot应用程序,以便在API调用上使用Authorization:Bearer&lt;access-token>工作?我需要什么依赖项/启动器,并且应如何配置这些内容?

更新:

我尝试添加:

<dependency>
  <groupId>org.springframework.security.oauth</groupId>
  <artifactId>spring-security-oauth2</artifactId>
  <version>2.3.7.RELEASE</version>
</dependency>

使用:

@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class OAuth2ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("my-azure-b2c-test");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/**")
            .authenticated();
    }
}

但是,当我在我的Spring Boot应用程序上发出请求时,我遇到了带有“invalid_token”错误的401。


你尝试过什么吗? - Michael
您需要在每个传入请求中检查Spring Boot应用程序中包含的JWT令牌(位于请求标头中)。 - ieggel
@ieggel,你能详细解释一下应该如何做吗? - Wim Deblauwe
@Michael,我更新了问题并添加了尝试过的内容。 - Wim Deblauwe
@WimDeblauwe 我没有使用Azure的经验,但我之前提到的是通常情况下应该如何完成。在我看来,您正在使用的库已经可以为您处理JWT验证并将其集成到Spring安全上下文中。这里似乎有一些示例:https://github.com/microsoft/azure-spring-boot/tree/master/azure-spring-boot-samples - ieggel
1个回答

4

一旦你知道解决方案,它似乎非常简单。

首先,添加以下依赖项:

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-resource-server</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

接下来,在你的application.properties文件中指定spring.security.oauth2.resourceserver.jwt.jwk-set-uri属性。

要知道这个值,请使用cURL或其他工具在https://<my-tenant-id>.b2clogin.com/<my-tenant-id>.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_<my-custom-policy>上执行GET操作。

这将返回一个带有jwks_uri值的JSON主体。将该值放入你的application.properties文件中。

现在,在项目中创建以下Java类:

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/**")
            .authenticated()
            .and()
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
    }
}

如果你现在有这样的控制器:
@RestController
public class ApiController {

    @GetMapping("/api/test")
    public String apiTest(@AuthenticationPrincipal Principal principal) {
        return "test " + principal;
    }
}

如果您使用正确的 Authorization 标头(且其类型为 org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken),在对 api/test 进行 GET 请求时,您将看到主体不为空。唯一不幸的是,这个主体没有权限,我仍然需要找出原因。

嗨@Wim,感谢您的解释。我尝试了同样的方法,它运行良好。正如您所提到的,在我的情况下,Principal也为Null。您有找到任何解决方法吗?再次感谢! - deen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接