在OAuth2 SSO中禁用Spring Boot应用程序中的CSRF。

8
我是一名有用的助手,可以为您翻译以下内容:

我有一个使用OpenID Connect/OAuth2通过Okta Platform API对用户进行身份验证的Spring Boot服务。当用户尝试访问我的服务时,他们将被重定向到Okta登录页面进行认证,然后Okta将它们重定向回我的服务。

这是我pom.xml文件中相关的部分

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这是我的控制器代码:

@RestController
@EnableOAuth2Sso
@SpringBootApplication
public class Application {

    @RequestMapping(path = "/", method = RequestMethod.GET)
    public String home(Authentication auth) {
        return "Home: " + auth.getName();
    }

    @RequestMapping(path = "/app", method = RequestMethod.POST)
    public String app(Authentication auth) {
        return "App: " + auth.getName();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

对于第一个GET控制器方法,这很完美,但对于第二个POST方法,我的服务要求我提供CSRF令牌。我想完全禁用CSRF检查,所以我将其添加到我的应用程序中。

@Configuration
@EnableOAuth2Sso
public class Config extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

然而,添加上述配置后,我的服务停止了使用Okta进行用户认证(不再将未经身份验证的请求重定向到Okta),它直接调用home()方法,并传递null参数。
我按照这篇博客文章创建了我的服务 https://developer.okta.com/blog/2017/03/21/spring-boot-oauth 如何在仍然使用OAuth2 SSO认证与Okta的情况下完全禁用CSRF?

你尝试过将 javax.security.Principal 注入到你的 home() 方法中,而不是使用 Authentication 吗? - Matt Raible
@danze 你解决了吗?如果是,请发布答案。 - Akshatha S R
3个回答

4

我遇到了完全相同的问题。经过对HttpSecurity类工作原理的深入挖掘,我修改了configure()函数如下:

    @EnableWebSecurity
public static class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests().anyRequest().authenticated().and().oauth2Login().and().csrf().disable();
    }
}

添加构建器子句 authorizeRequests().anyRequest().authenticated().and().oauth2Login() 强制控制器拦截OAuth身份验证请求。您可以在Spring HttpSecurity.java源代码中找到完整的文档。

为了确保,我修改了所有REST端点方法,将令牌作为参数包含在内。我发现,在原始版本的configure()方法中,令牌为空,但一旦添加了额外的子句,令牌就被包括进来了。


0
@Configuration
@EnableOAuth2Sso
public class Config extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

这对我没有起作用。相反,我为每个POST请求添加了CSRF头。

如果您正在使用Thymeleaf,则可以在.html文件中添加以下内容以获取CSRF令牌:

<html xmlns:th="http://www.thymeleaf.org">
<script th:inline="javascript">
function getToken(){
        var _csrf_token = [[${_csrf.token}]] ;
        var _csrf_param_name = [[${_csrf.parameterName}]];
        console.log(_csrf_token);
        return _csrf_token;
    }
</script>
</html>

然后将此作为标头放入您的ajax请求中

function sampleFunc(url, token) {


        $.ajax({
            type : 'POST',
            contentType : "application/json",
            url : '/storeTokens',
            beforeSend : function(xhr) {
                xhr.setRequestHeader('X-CSRF-TOKEN', token);
            },
            data : jsonObject
        // dataType : 'html'
        }).done(function(data) {
            console.log("success");

        }).fail(function(jqXhr) {
            var a = jqXhr;
        });

    }

这对我有用。


0

您需要仅针对 /app 端点禁用 CSRF 令牌。请尝试以下操作:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.mvcMatcher("/app").csrf().disable();
}

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