Oauth2Login 仅用于特定的 url

Posted

技术标签:

【中文标题】Oauth2Login 仅用于特定的 url【英文标题】:Oauth2Login for only specific urls 【发布时间】:2020-10-16 11:08:20 【问题描述】:

我正在尝试为通过 Spring Security 登录设置 oauth2 配置。但仅适用于特定的网址。

我的安全配置如下所示。

@Override
public void configure(HttpSecurity http) throws Exception 
    http
            .antMatcher("/secured/**")
            .authorizeRequests()
            .anyRequest()
            .authenticated()
    .and()
    .oauth2Login()
    .clientRegistrationRepository(clientRegistrationRepository())
    .authorizedClientService(authorizedClientService());

基本上,我只希望 oauth2Login 触发以 /secured 开头的 url。它似乎几乎可以工作,唯一的问题是每当 Spring 尝试将我的会话重定向到 google 进行身份验证时,它都会触发 404。

oauth 身份验证的标准重定向应该触发到 http://localhost:8080/oauth2/authorization/google,我的应用程序尝试这样做,但它是 404。

我假设 http://localhost:8080/oauth2/authorization/google url 被某种类型的安全配置阻止?但我终其一生都无法弄清楚原因。

我猜我需要为任何转到“/oauth2/authorization/**”的请求找到正确的 .permitAll() 组合

我已经在下面尝试过。

    @Override
public void configure(HttpSecurity http) throws Exception 
    http
            .antMatcher("/secured/**")
            .authorizeRequests()
            .antMatchers("/oauth2/authorization/**")
            .permitAll()
            .anyRequest()
            .authenticated()
    .and()
    .oauth2Login()
    .clientRegistrationRepository(clientRegistrationRepository())
    .authorizedClientService(authorizedClientService());

但这不起作用.....有人看到我的问题吗?我没有其他与此冲突的安全配置,我有点茫然。

【问题讨论】:

【参考方案1】:

根据之前的回答,没有 lambda-style 的版本应该是这个样子吧?

@Override
public void configure(HttpSecurity http) throws Exception 
    http
            .authorizeRequests
            .antMatchers("/secured/**").authenticated()
            .anyRequest().authenticated()
            .and()
            .oauth2Login()
            .clientRegistrationRepository(clientRegistrationRepository())
            .authorizedClientService(authorizedClientService());

如果我们只希望 "/secured/**" 使用 oauth2Login,为什么我们要使用 authenticated() 来处理 antMatcher("/secured/**")anyRequest()(而不是 permitAll() 来处理 anyRequest())?

谢谢。

【讨论】:

感谢您指出这一点。我已按照您的建议使用 permitAll() 使用正确的配置更新了我的回复。【参考方案2】:

了解这里问题的第一步是了解http.antMatcher()http.authorizeRequests() 之间的区别。

让我们看看下面的配置。 (我正在使用 Spring Security 5.2 中可用的 lambda 样式配置,以使其更具可读性)

@Override
public void configure(HttpSecurity http) throws Exception 
    http
            .antMatcher("/secured/**")
            .authorizeRequests(authorize -> authorize
                    .anyRequest().authenticated()
            )
            .oauth2Login(oauth2Login -> oauth2Login
                    .clientRegistrationRepository(clientRegistrationRepository())
                    .authorizedClientService(authorizedClientService())
            );

在这里,我们指定只有在匹配 "/secured/**" 时才会调用 HTTP 安全性。

换句话说,只有SecurityFilterChain匹配"/secured/**"的请求才会被处理。

这是一个问题,因为SecurityFilterChain 是从"/oauth2/authorization/google" 发起授权请求的原因。

但是,SecurityFilterChain 没有被调用,因为"/oauth2/authorization/google""/secured/**" 不匹配。

请考虑以下配置。

@Override
public void configure(HttpSecurity http) throws Exception 
    http
            .authorizeRequests(authorize -> authorize
                    .antMatchers("/secured/**").authenticated()
                    .anyRequest().permitAll()
            )
            .oauth2Login(oauth2Login -> oauth2Login
                    .clientRegistrationRepository(clientRegistrationRepository())
                    .authorizedClientService(authorizedClientService())
            );

在这里,将为所有请求调用 HTTP 安全性。

但是,只有匹配 "/secured/**" 的请求才会要求用户进行身份验证。

【讨论】:

【参考方案3】:

@eleftheria-stein-kousathana 的回答让我想到了另一个可能的解决方案。

如上所述,重要的是要知道不会调用 OAuth 端点,因为它们的安全配置绑定到直接跟在 HttpSecurity 对象之后的 antMatcher() 调用。

但正如docs 中所述,您还可以更改redirectionEndpointauthorizationEndpoint 的baseUris

@Override
public void configure(HttpSecurity http) throws Exception 
    http
            .antMatcher("/secured/**")
            .authorizeRequests()
            .anyRequest()
            .authenticated()
    .and()
    .oauth2Login()
       //New Code Starting here
       .authorizationEndpoint()
          .baseUri("/secured/oauth2/authorization")
        .and()
        .redirectionEndpoint()
          .baseUri("/secured/oauth2/code/*")
        .and()
       //new code ending here
    .clientRegistrationRepository(clientRegistrationRepository())
    .authorizedClientService(authorizedClientService());

请务必更改 clientRegistrationredirectUriTemplate 以及在 AuthorizationServer 上配置的重定向 uri

并且一定要在redirectionEndpoint.baseUri 的末尾添加星号...这花了我几分钟来找出问题所在:-)

【讨论】:

以上是关于Oauth2Login 仅用于特定的 url的主要内容,如果未能解决你的问题,请参考以下文章

NVActivityIndi​​catorView 仅用于特定视图

oauth2Login 和 oauth2Client 有啥区别?它们的用例是啥?

用于密码验证的正则表达式,仅特定字符 [重复]

仅提取特定文件名然后将其用于变量的 Bash 脚本

用于仅从字符串中删除特定特殊字符的正则表达式

换行换行符不适用于 UILabel 仅适用于特定文本字符串