SpringSecurtiy OAuth2 (5) Client Credentials Grant - 客户端模式

文章目录

  • 关于
    • 适用场景
    • 整体流程
  • 实现
    • 代码结构
    • 授权服务器 (Authorization Server)
      • AuthorizationServerConfiguration
      • SecurityConfiguration
    • 资源服务器 (Resource Server)
      • ResourceServerConfiguration
  • 测试
  • 总结

关于 SpringSecurity OAuth2 的 4 种模式的简要介绍性文章:
SpringSecurtiy OAuth2 (2) Authorization Code Grant - 授权码模式
SpringSecurtiy OAuth2 (3) Implicit Grant - 隐式授权模式
SpringSecurtiy OAuth2 (4) Resource Owner Password Grant - 密码模式
SpringSecurtiy OAuth2 (5) Client Credentials Grant - 客户端模式


更多细节和底层原理, 稍后会有专门的文章介绍.

关于

适用场景

适用于应用没有前端, 只有后端. 整个授权过程没有用户介入 (注意, 虽然密码模式也不需要前端, 但是是有用户信息介入的, 客户端授权模式是 4 种模式中唯一一种完全不需要用户介入的模式). 是第三方应用和授权服务器之间, “应用级别” 的行为.
直接与授权服务器交互, 用授权服务器颁发的客户端 ID 和客户端密钥直接去申请访问令牌.
请求 URL 形如:

http://localhost:18709/client-credentials-authorization-server/oauth/token?grant_type=client_credentials&client_id=client-a&client_secret=client-a-p

主要用于第一方应用.
譬如之前在公司中台做了一个对应全公司与外部多方财务系统的财务中间服务, 对内, 就是采取的客户端模式, 将公司内部产品视作客户端, 均要去中间服务申请客户端 ID 和客户端密钥, 然后在用这个凭证信息换取访问令牌以访问中间服务的资源.

整体流程

SpringSecurtiy OAuth2 (5) Client Credentials Grant - 客户端模式_第1张图片

实现

代码结构

├─client-credentials-authorization-server
│  │  pom.xml
│  │  README.md
│  │  
│  └─src
│     └─main
│         ├─java
│         │  └─c
│         │      └─c
│         │          └─d
│         │              └─s
│         │                  └─s
│         │                      └─o
│         │                          └─c
│         │                              └─c
│         │                                  └─authorization
│         │                                      └─server
│         │                                          │  ClientCredentialsAuthorizationServer.java
│         │                                          │  
│         │                                          └─configuration
│         │                                                  AuthorizationServerConfiguration.java
│         │                                                  SecurityConfiguration.java
│         │                                                  
│         └─resources
│                 application.yml
│                 
└─client-credentials-resource-server
   │  pom.xml
   │  
   └─src
      └─main
          ├─java
          │  └─c
          │      └─c
          │          └─d
          │              └─s
          │                  └─s
          │                      └─o
          │                          └─c
          │                              └─c
          │                                  └─resource
          │                                      └─server
          │                                          │  ClientCredentialsResourceServer.java
          │                                          │  
          │                                          ├─configuration
          │                                          │      ResourceServerConfiguration.java
          │                                          │      
          │                                          └─controller
          │                                                  ResourceController.java
          │                                                  
          └─resources
                  application.yml

授权服务器 (Authorization Server)

AuthorizationServerConfiguration

由于客户端模式本身就是描述客户端和授权服务器之间的行为的, 所以在客户端模式的授权服务器代码中, 不需要额外指定其他的

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security.allowFormAuthenticationForClients().checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // @formatter:off
        clients.inMemory()
                .withClient("client-a")
                .secret(passwordEncoder.encode("client-a-p")).resourceIds("resource-server")
                .authorizedGrantTypes("client_credentials")
                .scopes("access-resource")

                .and()
                .withClient("resource-server").secret(passwordEncoder.encode("resource-server-p"))
        ;
        // @formatter:on
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        super.configure(endpoints);
    }

    // ~ autowired
    // -----------------------------------------------------------------------------------------------------------------

    @Autowired
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    // ~ bean
    // -----------------------------------------------------------------------------------------------------------------

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

SecurityConfiguration

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.formLogin().disable();
        http.httpBasic().disable();
        http.authorizeRequests().anyRequest().authenticated();
        // @formatter:on
    }
}

资源服务器 (Resource Server)

ResourceServerConfiguration

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId("resource-server").tokenServices(remoteTokenServices()).stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated();
    }

    private RemoteTokenServices remoteTokenServices() {
        final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
        remoteTokenServices.setCheckTokenEndpointUrl("http://localhost:18709/client-credentials-authorization-server/oauth/check_token");

        // 客户端授权模式没有用户介入, 是应用程序和应用程序间的交互
        remoteTokenServices.setClientId("resource-server");
        remoteTokenServices.setClientSecret("resource-server-p");
        return remoteTokenServices;
    }
}

测试

SpringSecurtiy OAuth2 (5) Client Credentials Grant - 客户端模式_第2张图片

总结

简单过了一遍最后一种授权模式: 客户端授权.
总的来说授权码模式隐式模式都需要前端和用户介入, 其中隐式模式甚至可以不需要后端; 密码模式虽然不需要前端支持, 但是仍然需要用户凭证; 而这最后一种客户端模式, 完全不需要用户介入, 是纯粹的客户端与授权服务器之间的行为. 非常适用于内部系统间的认证鉴权.


- To Be Continued -
- 接下来, 我们会详细探讨 Spring Security OAuth2 的更多自定义特性. 包含 ClientDetailsService, TokenGranter etc.

你可能感兴趣的:(#,Spring,Security)