【问题标题】:How to secure a MVC application with OAuth2 using Spring?如何使用 Spring 使用 OAuth2 保护 MVC 应用程序?
【发布时间】:2018-11-08 19:05:31
【问题描述】:

对不起,我的英语。

我有一个应用程序,我可以用通常的方式登录。

@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("LoginSecurityConfig :: configure");

        auth.jdbcAuthentication().dataSource( getDataSource() )
            .passwordEncoder( new BCryptPasswordEncoder(16) )
            .usersByUsernameQuery(
                "select user_name as username,password,enabled from users where user_name=?")
            .authoritiesByUsernameQuery(
                "select user_name as username, role_name from users_roles ur join users u on ur.user_id = u.user_id and u.user_name = ?");

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/login*").anonymous()
        .antMatchers("/resources/**").permitAll()
        .antMatchers("/fotos/**").permitAll()
        .antMatchers("/users").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/user").access("hasRole('ROLE_ADMIN')")
        .anyRequest().authenticated()
        .and()

        .formLogin()
        .loginPage("/loginPage")
        .defaultSuccessUrl("/home", true)
        .failureUrl("/loginPage?error=true")
        .loginProcessingUrl("/login")
        .usernameParameter("username")
        .passwordParameter("password")
        .and()

        .logout()
        .logoutSuccessUrl("/loginPage")
        .invalidateHttpSession(true); 



    }    

}

使用这个我可以尝试访问任何安全资源,系统将我发送到loginPage,我可以将usernamepassword发布到内部login控制器然后我有Principal并且可以访问受保护的资源(家庭、用户、用户)。工作正常。

但是...我需要删除用户控制数据库的内容并使用 OAuth2 来允许相同类型的访问。我不想再在我的数据库中有任何用户了。我需要一个登录屏幕,然后是像http://myserver/oauth/token?grant_type=password&username=admin&password=admin 这样的令牌请求,在Basic 中传递client_idclient_secret。我知道如何执行“获取令牌”部分,并且我的服务器工作正常并给我令牌和刷新令牌,但只使用 Postman,因为我不知道如何在我的 Web 应用程序代码中使用它。我发现的所有教程都在同一个应用程序中同时使用服务器和客户端,实际上并没有展示如何使用 OAuth2 远程服务器。

已经尝试使用this。这是一个很好的教程,非常接近我的需要,但对我来说太复杂了。

我有这段代码并且理解它可以使用服务器并使用客户端凭据发出令牌,但不知道如何为用户提供登录屏幕并获取他的凭据以完成请求(GET部分)。

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfigRemoteTokenService extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity http) throws Exception {
                http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                    .and()
                    .authorizeRequests().anyRequest().permitAll();              
    }

    @Primary
    @Bean
    public RemoteTokenServices tokenServices() {
        final RemoteTokenServices tokenService = new RemoteTokenServices();
        tokenService.setCheckTokenEndpointUrl("http://myoauthserver/oauth/check_token");
        tokenService.setClientId("clientid");
        tokenService.setClientSecret("password");
        return tokenService;
    }

}

所以...如何保护我的系统,从用户那里获取登录名和密码,并使用此代码来控制凭据,就像我使用通常的数据库方法一样?

或者 OAuth2 仅用于安全的 REST API?

请对新手友好,因为我不太习惯使用 Spring。

【问题讨论】:

    标签: spring-mvc spring-security-oauth2


    【解决方案1】:

    我自己最近一直在研究这个问题,我希望我可以说我有一个简单的答案,但我没有。我必须首先问一些问题,例如,这是 Web 应用程序(JSP 等)还是 Web 应用程序使用的 REST API,还是移动应用程序使用的 REST API 等等。

    这很重要的原因是您首先必须选择一个 OAuth2 配置文件和授权类型,它们在 Spring 中都有不同的要求和配置。

    此外,您是否尝试与第三方 OAuth2 身份验证提供程序(例如 Facebook)集成,或者您的应用程序是否同时充当身份验证提供程序(发生登录和密码验证)和受保护资源(网页请求或API调用去)?

    所以我想我能做的最好的就是给你布置一些作业:

    (1) 阅读各种 OAuth2 配置文件并确定最适合您的应用程序的配置文件,并了解所有术语(例如,什么是客户端密码?)。

    这绝对不是您可以在不理解示例代码的情况下剪切和粘贴示例代码的情况之一。如果您对 OAuth2 的工作原理没有合理的理解,您将会遇到很多困难。

    另外:我们在这里谈论的是安全性,所以在不了解的情况下做事是一个非常糟糕的主意。如果您不小心,您可能会认为它在起作用,但实际上您正在让自己对攻击敞开大门。

    (2) 如果您不熟悉 Spring 框架安全性,则需要有一个基本的基础才能理解您在做什么。

    (3) 确定要使用的个人资料后,请在 Google 搜索中使用该个人资料,例如“Spring oauth2 隐式授权”以查找针对该配置文件量身定制的示例。

    那里有一些示例,这是一个很好的起点,尽管我发现我无法将任何示例直接应用到我的应用程序中,因为它们的假设和我的应用程序存在细微差别。

    Spring 参考指南也很有帮助,但不一定提供您可能遇到的所有问题的所有详细信息。最后,尝试在您的应用程序中实现。

    您需要一些好的工具来向您的应用发送请求(我喜欢 PostMan),这样您就可以检查来回传输的数据。 OAuth2 涉及一系列复杂的 HTTP 重定向,因此测试可能有点困难。

    另外,请耐心等待。我认为自己是一名 Spring 专家,但我仍然花了几天时间才让事情完全按照我想要的方式工作。请注意,实际上您最终编写的代码非常少,但是要使少量代码完全正确是困难的。

    【讨论】:

    • 我有一个受信任的环境,其中包含一些 Web 应用程序,每个应用程序都有自己的安全数​​据库和登录方法。我只需要将所有用户和凭据集中在一个地方,以便我的所有 Web 应用程序都可以使用它。它是一组军事应用程序,在如此多的环境中管理同一用户是一场噩梦。很高兴在我的用户进入任何应用程序之前只有一个地方来确认他们,他可以在应用程序之间切换而无需一次又一次地登录。
    【解决方案2】:

    简单如 1,2,3 ...

    只需稍微更改我的 OAuth2 服务器以接受 oauth/authorize 方法。

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
        http
            .requestMatchers()
            .antMatchers("/login", "/oauth/authorize")
        .and()
            .authorizeRequests()
            .anyRequest()
            .authenticated()
        .and()
            .formLogin()
            .permitAll();       
    }
    

    并创建一个自定义登录表单。现在所有客户端(Web 应用程序)都可以登录了。

    您可以在此处找到示例客户端和更多详细信息:http://www.baeldung.com/sso-spring-security-oauth2

    您还可以在我的 github 存储库中检查我的整个服务器和客户端:

    https://github.com/icemagno/geoinfra/cerberus

    https://github.com/icemagno/geoinfra/atlas

    它在 pt_BR 中

    【讨论】:

      猜你喜欢
      • 2011-09-10
      • 2015-11-30
      • 2020-07-29
      • 2014-02-05
      • 2021-06-25
      • 2019-04-02
      • 2020-01-08
      • 2015-08-20
      • 2017-04-14
      相关资源
      最近更新 更多