当前位置: 首页 > 知识库问答 >
问题:

运行Spring Boot oAuth2应用程序作为资源服务器并提供web内容

东博瀚
2023-03-14

我使用的是Spring Boot 1.5.13、Spring Security 4.2.6和Spring Security oAuth2 2.0.15。

我想为我们的Spring Boot应用程序找到一个最佳实践设置,该应用程序提供一组混合内容:一个REST API,一些web页面为开发人员提供一个方便的“登陆页”,上面有一些链接,加上基于Swagger的API文档,这也是web内容。

我的配置允许我使用适当的授权代码流运行应用程序,因此我可以通过浏览器访问所有web内容,并由配置的IdP(在我的例子中是PingFederate)进行身份验证,此外,我可以在浏览器内进行API调用,即直接调用或使用REST客户端调用,例如使用RESTClient。

这是我的安全配置:

@Slf4j
@Configuration
@EnableWebSecurity
@EnableOAuth2Sso // this annotation must stay here!
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login**", "/webjars/**", "/css/**").permitAll()
                .antMatchers("/cfhealth").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/protected", "/api/**").authenticated();
    }

    @Bean
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }

}

和oAuth2配置:

@Configuration
@Slf4j
public class OAuth2Config extends ResourceServerConfigurerAdapter {

    @Value("${pingfederate.pk-uri}")
    String pingFederatePublicKeyUri;

    @Autowired
    PingFederateKeyUtils pingFederateKeyUtils;

    @Override
    public void configure(ResourceServerSecurityConfigurer config) {
        config.tokenServices(tokenServices());
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        String certificate = pingFederateKeyUtils.getKeyFromServer(pingFederatePublicKeyUri);
        String publicKey = pingFederateKeyUtils.extractPublicKey(certificate);
        converter.setVerifier(pingFederateKeyUtils.createSignatureVerifier(publicKey));
        return converter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }

}

但是,当我想通过编程方式/在浏览器外部使用头部中的承载令牌调用REST API,例如使用curl时,授权代码流会启动并重定向到本地登录endpoint。我想要的是,API调用接受承载令牌进行身份验证,而不创建会话,并且浏览器中的所有web Content/MVC调用都建立会话。

curl -i -H "Accept: application/json" -H "Authorization: Bearer $TOKEN" -X GET http://localhost:8080/authdemo/api/hello

将@enableResourceServer注释添加到上面的SecurityConfig类中(并在应用程序属性文件中添加security.oauth2.resource.filter-order=3,我可以使curl命令工作,但随后授权代码流中断,我在浏览器中为应用程序中的所有URL获得以下输出:

需要完全身份验证才能访问此资源 未经授权

现在有办法让这个szenario工作得很好吗?如果是,那会是什么样子?还是只在Spring boot+security+oauth2的较晚版本中支持?

使用安全OAuth2启动Spring时的问题--如何使用web登录表单的资源服务器?很相似

共有1个答案

谭新知
2023-03-14

我找到了解决方案:它需要多个HttpSecurity配置。通过阅读Matt Raible在https://developer.okta.com/blog/2018/02/13/secure-spring-microservices-with-oauth上写的一篇很棒的文章,我发现了这一点,他向我介绍了requestMatchers(.)的概念。这就是我最终如何实现的:

 @Configuration
 @EnableResourceServer
 @EnableWebSecurity(debug = true)
 @EnableOAuth2Sso
 public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

     @Bean
     public RequestContextListener requestContextListener() {
         return new RequestContextListener();
     }

     @Override
     public void configure(HttpSecurity http) throws Exception {
         http
             .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
             .authorizeRequests().anyRequest().fullyAuthenticated();
     }

 }

这样,我就可以用浏览器访问服务,从而产生授权代码流。但是访问API(或者实际上是服务的任何部分)会导致对所提供的承载令牌进行验证。

为了说明如何在这种情况下退出/公开一些endpoint,下面是我如何配置执行器endpoint和我自己添加的一个非常简单的“ping”endpoint:

 @Configuration
 @Order(1)
 public class ActuatorSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new OrRequestMatcher(EndpointRequest.to("health", "info"),
                 new AntPathRequestMatcher("/cfhealth"))).authorizeRequests().anyRequest().permitAll();
    }

 }

和/cfhealthendpoint的实现:

 @Controller
 @Slf4j
 public class MainController {

     @GetMapping(value = "/cfhealth")
     @ResponseBody
     public String cfhealth() {
         return "ok";
     }

 }

如果这是Spring Security配置的最佳实践方法,或者有更好的方法,我很乐意向其他人学习。在过去的几周里,我在这个主题上花了相当多的时间,要掌握基本的Spring Security概念需要付出相当多的努力。

 类似资料:
  • 问题内容: 我正在使用Docker部署我的ASP.NET Core Web API微服务,并且正在寻找将配置注入到每个容器中的选项。在应用程序根目录中使用appsettings.json文件的标准方法并不理想,因为据我所知,这意味着将文件构建到我的docker映像中,这将限制该映像可以在哪个环境中运行。 我想一次构建一个映像,可以在运行时为它们提供配置,并在整个开发过程中进行测试,测试UAT并进入

  • 问题内容: 我想将Java应用程序作为服务运行。不幸的是,我的局限性在于无法使用Java Service Wrapper之 类的工具(它确实是一种出色的工具)。 有什么方法可以在不依赖外部应用程序的情况下将可执行的JAR作为服务运行吗?我当前已安装该服务,但无法启动。这是我遇到的困扰,除了关于JSW的信息之外,我无法在Google上找到其他任何东西。 问题答案: 有Java Service Wra

  • 我有Spring Boot Web应用程序,最初是为内部Tomcat服务器构建的(有效)。然后我采用了该应用程序在Web Logic服务器上运行。我的应用程序编译并部署到服务器没有问题,但当它不服务MVC页面时。每次调用都会抛出404错误。从下面的错误看,它看起来像Spring调度程序servlet存在,但甚至区域设置都没有正确设置。我无法弄清楚这里有什么问题或缺失,但当我创建RestContro

  • 问题内容: 我正在探索Go的深度,并且我一直在尝试编写一个简单的Web应用程序来围绕所有内容。我正在尝试服务React.js应用程序。 下面是Go服务器的代码。我有默认的服务路线,效果很好。我正在努力允许将静态文件提供给该索引文件。尽管我需要静态提供JavaScript / CSS / Media文件,但我允许React App自己进行客户端路由。 例如,我需要能够将文件提供给React应用程序才

  • 我正在尝试将Microsoft Team BOT作为Azure Web应用程序运行-可以在此处找到完整的代码 application.py: 在本地运行时,我可以将端口设置为8000,例如,将ngrok指向localhost,并在我的bot通道注册中指定url,一切正常。我一直在努力让我的代码在Azure中工作,但我就是无法做到这一点。我已将脚本配置为在端口8000上运行,并在应用程序设置中设置参

  • 问题内容: 每当用户断开手机通话时,我都希望显示自定义弹出消息。问题是如何检测应用程序何时未运行。任何线索都将有所帮助。 问题答案: 已经有一段时间了,并且已经有了很多发展。 首先,如何在Flutter中创建服务以使应用程序始终在后台运行有一些答案? 此外,使用Flutter插件和地理围栏(在2018年9月),Flutter / Background流程 基本上将使您指向在后台执行中等/执行Dar