SpringOauth2 Authorization_code 模式(一)

1. Oauth2 authorization_code 认证协议说明

Oauth2 Authorization_code 模式是 Oauth2 认证中最完善的认证方式。其完整的认证模式如下:
SpringOauth2 Authorization_code 模式(一)_第1张图片

  • (A)用户访问客户端,客户端将用户引导向认证服务器。
  • (B)用户选择是否给予客户端授权。
  • (C)如用户给予授权,认证服务器将用户引导向客户端指定的redirection uri,同时加上授权码code。
  • (D)客户端收到code后,通过后台的服务器向认证服务器发送code和redirection uri。
  • (E)认证服务器验证code和redirection uri,确认无误后,响应客户端访问令牌(access token)和刷新令牌(refresh token)

以上就是Oauth2 code 认证的基本方式!


2.SpringSecurtiy中 Oauth2 code认证

在SpringSecurtiy中 Oauth2 code认证过程基本上符合上面所说的Oauth2 authorization_code 协议的认证过程。SpringSecurity中整合了Oauth2协议,由于SpringSecurity的本质是一系列的过滤器链组成。所以在加入Oauth2协议以后,相当于在SpringSecurity的过滤器链中,加上Oauth2认证的过滤链实现认证服务。


3.SpringSecurtiy中 Oauth2 code的代码实现

3.1 Maven 依赖,spring-boot版本为:2.0.5.RELEASE
    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.5.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
        Finchley.SR1
        1.3.2
    

    
        
            org.springframework.boot
            spring-boot-starter-security
        
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.security.oauth
            spring-security-oauth2
            2.3.3.RELEASE
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.security
            spring-security-test
            test
        
        
            mysql
            mysql-connector-java
            runtime
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            ${mybatis.version}
        

        
            org.springframework.boot
            spring-boot-starter-jdbc
        

        
            org.springframework.boot
            spring-boot-starter-data-redis
        

        
        
            org.apache.commons
            commons-pool2
        

    

    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

3.2 SpringSecurity 安全配置类实现:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    PasswordEncoder passwordEncoder;

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

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic().and().authorizeRequests()
                .antMatchers("/oauth/**","/login")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and().csrf().disable();
    }

    @Bean
    @Override
    protected UserDetailsService userDetailsService(){
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("hello1").password(passwordEncoder.encode("123456")).authorities("USER").build());
        manager.createUser(User.withUsername("hello2").password(passwordEncoder.encode("123456")).authorities("USER").build());
        return manager;
    }
}
3.3 资源服务器实现代码
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/oauth/**")
                .permitAll()
                .anyRequest()
                .authenticated();
    }
}
3.4 认证服务器实现代码
@Configuration
@EnableAuthorizationServer
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
                .realm("oauth2-resources")
                //url:/oauth/token_key,exposes public key for token verification if using JWT tokens
                .tokenKeyAccess("permitAll()")
                //url:/oauth/check_token allow check token
                .checkTokenAccess("isAuthenticated()")
                .allowFormAuthenticationForClients();
    }

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

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client")
                .secret(passwordEncoder.encode("secret"))
                .redirectUris("http://example.com")
                .authorizedGrantTypes("authorization_code", "client_credentials", "refresh_token",
                        "password", "implicit")
                .scopes("all")
                .resourceIds("oauth2-resource")
                .accessTokenValiditySeconds(1200)
                .refreshTokenValiditySeconds(50000);
    }
}

整个认证服务器和资源服务器的代码基本上已经实现。下面我们进行测试配合code认证的流程进行说明。


4.请求认证

4.1 请求认证参数URL
http://localhost:8080/oauth/authorize?response_type=code&client_id=client1&redirect_uri=http://example.com&scop=all

参数说明:

client_id:客户端的ID,必选项  
redirect_uri:重定向URI,必选项  
scope:申请的权限范围,可选项  
state:任意值,认证服务器会原样返回,用于抵制CSRF(跨站请求伪造)攻击。

如果当前用户没有登录的话,会重定向到登录页面,强制用户进行登录认证。
这个步骤相当于:

  • (A)用户访问客户端,客户端将用户引导向认证服务器。
  • (B)用户选择是否给予客户端授权。

登录后认证服务器会进行授权,授权通过之后会产生一个code码:

http://example.com/?code=03cQZu

code码只能使用一次。

注意:这里的redirect_uri=http://example.com 必须配置在ClientDetailsServiceConfigurer 中,不然会抛出异常:

{"error":"invalid_grant","error_description":"Redirect URI mismatch."}
4.2 携带code获取token
curl -i -d "grant_type=authorization_code&code=gnyW4f&client_id=client&client_secret=secret&redirect_uri=http://example.com" -X POST http://localhost:8080/oauth/token

请求参数说明:

client_id:客户端的ID,必选项。  
client_secret:客户端的密钥,必选项。  
grant_type:表示使用的授权模式,必选项。 
refresh_token:表示早前收到的更新令牌,必选项。
redirect_uri:当前版本必选项

返回值:

{
    "access_token": "10337f46-fe9b-4914-9f1b-15d3bfd6227b",
    "token_type": "bearer",
    "refresh_token": "1cc55626-9fc0-47ac-8f3f-685abd11deaf",
    "expires_in": 990,
    "scope": "all"
}

返回参数说明:

access_token:访问令牌,必选项。  
token_type:令牌类型,该值大小写不敏感,必选项。  
expires_in:过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。  
refresh_token:更新令牌,用来获取下一次的访问令牌,可选项。  
scope:权限范围,如果与客户端申请的范围一致,此项可省略。
4.3 check_token
curl -i -X POST -H "Accept: application/json" -u "client:secret" http://localhost:8080/oauth/check_token?token=a388c2fa-2243-4b7a-b8c5-09973cde4fb2

返回值:

{
    "aud": [
        "oauth2-resource"
    ],
    "user_name": "hello1",
    "scope": [
        "all"
    ],
    "active": true,
    "exp": 1539929197,
    "authorities": [
        "USER"
    ],
    "client_id": "client"
}
4.4 refresh_token
curl -i -d "grant_type=refresh_token&refresh_token=8b6c262d-22cb-4e5b-af08-a32cbee5c5c2" -u "client:secret" -X POST http://localhost:8080/oauth/token

返回结果:

{
    "access_token": "3de40530-a9cf-44ce-a0ef-1165a11add1d",
    "token_type": "bearer",
    "refresh_token": "8b6c262d-22cb-4e5b-af08-a32cbee5c5c2",
    "expires_in": 1199,
    "scope": "all"
}

你可能感兴趣的:(springOauth2.0)