实现授权代码流授予类型OAuth2

时间:2018-05-24 18:04:11

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

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

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

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

现在我有以下查询:

  1. 哪种授权类型最适合我的需要,从我所看到的授权代码授权类型似乎是合适的?或者它是隐含的吗?

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

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

    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
    

1 个答案:

答案 0 :(得分:0)

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

OAuth2 grant types introduction and comparison

注意:有关完整的解释,请访问https://blog.oauth.io/oauth2-flow-grant-types-in-pictures/

回答您的问题:

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

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

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

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

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

Resource Owner Password Credential and Authorization Code full flow comparison

注意:

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

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

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

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

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

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

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

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