【问题标题】:Implementing authorization code flow grant type OAuth2实现授权码流授权类型 OAuth2
【发布时间】:2018-11-04 01:08:58
【问题描述】:

我在这里遇到了真正的问题,需要您的帮助。我在一家银行工作,并被分配了使用 Spring Boot 实现 OAuth2 服务的任务,我从上周开始一直在探索,并且能够实现密码流授权类型 OAuth2 服务,但现在我有几个问题我的前辈说密码流不适合我们的用例。首先我想解释一下用例:

第 1 步:用户将点击无需登录的 Web 应用程序的应用程序 URL,并且在应用程序加载之前,OAuth2 服务将使用已登录的 AD(系统)用户 ID 命中。

第 2 步。OAuth2 服务应使用具有给定用户 ID 的 ldap 对用户进行身份验证,并返回用户所属的所有组以及访问令牌,之后将用于访问 API

现在我有以下查询:

  1. 哪种授权类型最适合我的需要,从我所阅读的授权代码授权类型似乎是合适的?还是隐含的?

  2. 根据问题 1 的答案,我需要在以下代码中进行哪些代码更改:

我的授权服务器的代码 sn-p:

Oauth2AuthserverApplication.java

     @SpringBootApplication
     @EnableAuthorizationServer
     public class Oauth2AuthserverApplication {

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

OAuth2Congig.java

   @Configuration
   public class Oauth2Config extends AuthorizationServerConfigurerAdapter {

   private String clientId = "client";
   private String clientSecret = "secret";
   private String privateKey = "private-key";
   private String publicKey = "public-key";


  @Autowired
  @Qualifier("authenticationManagerBean")
  private AuthenticationManager authenticationManager;

  @Bean
  public JwtAccessTokenConverter tokenEnhancer() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey(privateKey);
    converter.setVerifierKey(publicKey);
    return converter;
  }

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

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
             throws Exception {
          endpoints.authenticationManager(authenticationManager).
              tokenStore(tokenStore())
                  .accessTokenConverter(tokenEnhancer());
  }

  @Override
  public void configure(AuthorizationServerSecurityConfigurer security) 
                 throws Exception {
          security.tokenKeyAccess("permitAll()").
              checkTokenAccess("isAuthenticated()");
  }

  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws 
               Exception {

     clients.inMemory().withClient(clientId).
           secret(clientSecret).scopes("read", "write")
            .authorizedGrantTypes("password", 
                 "refresh_token").accessTokenValiditySeconds(20000)
            .refreshTokenValiditySeconds(20000);

     }

  }

SecurityConfiguration.java

   @Configuration
   @EnableWebSecurity
   @EnableGlobalMethodSecurity(prePostEnabled = true)
   public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

   @Autowired
   CustomDetailsService customDetailsService;

   @Bean
   public PasswordEncoder encoder() {
    return new BCryptPasswordEncoder();
   }

   @Override
   @Autowired
   protected void configure(AuthenticationManagerBuilder auth) throws 
              Exception {
          auth.userDetailsService(customDetailsService).
                    passwordEncoder(encoder());
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {
             http.authorizeRequests().anyRequest().authenticated().
                  and().sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
   }

   @Override
   @Bean
   public AuthenticationManager authenticationManagerBean() throws Exception 
       {
           return super.authenticationManagerBean();
   }
 }

不粘贴授权服务器类的模型、dao和服务代码,因为它们与本题无关。

来自资源服务器项目的代码片段:

OAuth2ResourceserverApplication.java

   @SpringBootApplication
   @EnableResourceServer
   @RestController
   public class Oauth2ResourceserverApplication {

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


     @RequestMapping(value="/api")
     public String success() {
         return "SUCCESS";
     }
  }

JwtConverter.java

  @Component
  public class JwtConverter extends DefaultAccessTokenConverter implements 
           JwtAccessTokenConverterConfigurer {

     @Override
     public void configure(JwtAccessTokenConverter converter) {
              converter.setAccessTokenConverter(this);
     }
  }

SecurityConfiguration.java

   @Configuration
   @EnableWebSecurity
   @EnableGlobalMethodSecurity(prePostEnabled = true)
   public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
     http.authorizeRequests().anyRequest().authenticated().
                  and().sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.NEVER);
   }
 }

application.yml

 server:
 port: 8081
 security:
 oauth2:
    resource:
        filter-order: 3 
        jwt: 
            key-value: private-key

【问题讨论】:

    标签: java spring-boot spring-security oauth-2.0 spring-security-oauth2


    【解决方案1】:

    OAuth2 有 4 种授权类型。为了快速了解“资源所有者密码凭据”、“授权码”、“隐式”之间的区别,让我们将它们并排比较:

    注意:完整的解释见:https://blog.oauth.io/oauth2-flow-grant-types-in-pictures/

    回答你的问题:

    1. 哪种授权类型最适合我的需要,从我所阅读的授权代码授权类型似乎是最合适的?还是隐含的?

    如果您根据紫色条的“安全性”进行比较,“授权码”是最好的。但是您可以看到它具有代表 App(前端)执行对用户数据存储的访问的 Guard(后端)的概念,即,App 永远无法直接访问 Key/Access Token,因为 Key 是通过用户和 OAuth 服务器之间的用户名/密码交换来检索的,然后传递给 Guard。

    您实施的“资源所有者密码凭据”是最不安全的,因为用户名/密码已移交给应用程序,以便应用程序在未经用户进一步同意的情况下执行用户可以执行的所有操作。但是,在您的场景中,App 和 User 数据存储都属于您,从而缓解了安全问题。

    1. 根据问题 1 的答案,我需要在以下代码中进行哪些代码更改:

    您实现的资源所有者密码凭据授权类型的完整流程是下图的左侧部分,授权代码授权类型是右侧部分。如您所见,一般有5个步骤。对于资源所有者密码凭据,某些步骤不是必需的,即标记为“N.A.”。

    注意:

    • “云”代表应用程序
    • “www”代表用户/浏览器
    • “安全”代表 OAuth 服务器

    要从左侧到右侧,您需要进行的更改是:

    步骤 1. 如果您的 OAuth 服务器要支持不同的应用程序,那么它需要支持应用程序预注册以获取客户端 id/secret。如果你只有一个应用程序,那么你可以跳过这个。

    第 2 步。应用程序不再提示输入用户名/密码,而是将用户重定向到 OAuth 服务器以执行用户名/密码身份验证

    第 3 步。在验证用户身份后,OAuth 服务器可以提示用户她想要授予应用程序的权限类型(例如,阅读电子邮件、更新个人资料等)

    第 4 步。OAuth 服务器不是将密钥/访问令牌交给应用程序,而是将代码交给用户,然后用户将其传递给应用程序

    第 5 步。应用程序随后与 OAuth 服务器交换密钥/访问令牌的代码。

    获得密钥/访问令牌后,您可以调用不同服务器上的任何受保护 API,然后在响应 API 请求之前使用 OAuth 服务器验证密钥/访问令牌,例如,返回用户所属的组.

    【讨论】:

      猜你喜欢
      • 2021-04-24
      • 2018-05-26
      • 2020-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 2018-10-02
      • 1970-01-01
      相关资源
      最近更新 更多