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

步骤1:用户将点击不需要登录的Web应用程序的应用程序URL,并且在应用程序加载之前,将使用登录的AD(系统)用户ID来访问OAuth2服务。

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

现在我有以下查询:


从我阅读的授权代码授予类型看来,哪种授予类型最适合我的需求?还是隐含的?
根据问题1的答案,我需要在以下代码中进行哪些代码更改:


我的授权服务器的代码段:

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

最佳答案

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

java - 实现授权代码流授予类型OAuth2-LMLPHP

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

要回答您的问题:


从我阅读的授权代码授予类型看来,哪种授予类型最适合我的需求?还是隐含的?


如果您根据“安全性”紫色条进行比较,则“授权代码”是最好的。但是,您可以看到它具有Guard(后端)的概念,该概念代表App(前端)执行对User数据存储区的访问,即,App从不直接访问密钥/访问令牌,因为通过用户与OAuth服务器之间的用户名/密码交换来检索密钥,然后将其传递给Guard。

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


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


您实现的“资源所有者密码凭证”授予类型的完整流程在下图的左侧,“授权代码”授予类型在右侧。如您所见,通常有5个步骤。对于资源所有者密码凭证,不需要执行某些步骤,即标记为“ NA”。

java - 实现授权代码流授予类型OAuth2-LMLPHP

注意:


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


要从左侧到右侧,您需要进行以下更改:

步骤1.如果您的OAuth服务器要支持其他应用程序,则它需要支持应用程序预注册以获取客户端ID /秘密。如果只有一个应用程序,则可以跳过此步骤。

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

步骤3.验证用户身份后,OAuth服务器可以提示用户要授予该应用程序什么样的权限(例如,阅读电子邮件,更新个人资料等)。

步骤4. OAuth服务器没有将密钥/访问令牌交给应用程序,而是将代码交给了用户,然后用户将该代码传递给了应用程序

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

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

10-07 16:16
查看更多