Spring Cloud Finchley | Spring Cloud OAuth2

版权声明:写文章不赚钱,就是交个朋友。微信公众号【Mr sirius】 https://blog.csdn.net/Sirius_hly/article/details/89855925

一.简介

OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。
在APP或者网页接入一些第三方应用时,时长会需要用户登录另一个合作平台,比如QQ,微博,微信的授权登录。

OAuth 提供三种角色,分别是:

  • 服务提供方(Authorization Server)
  • 资源持有者(Resource Server)
  • 客户端(Client)

认证流程如下:

  • 1.用户(资源持有者)打开客户端,客户端询问用户授权。
  • 2.用户同意授权。
  • 3.客户端向授权服务器申请授权。
  • 4.授权服务器对客户端进行认证,包括用户信息认证,认证成功后授予令牌。
  • 5.客户端获取令牌后,携带令牌向资源服务器请求资源。
  • 6.资源服务器确定令牌正确无误,向客户端释放资。

在这里插入图片描述
在这里插入图片描述

二.Spring Cloud OAuth2 的使用

本实例包含三个服务,服务注册中心(server-service),客户端(client-service),以及授权服务(oauth-service),客户端和授权服务向注册中心注册,授权服务负责授权给客户端,之后客户端能访问相关的资源。

Spring OAuth2 分为两部分,分别是:

  • OAuth2 Provider
  • OAuth2 Client

OAuth2 Provider 负责公开被OAuth保护起来的资源,需要配置代表用户的OAuth 客户端信息,被允许的用户就可以访问被oauth保护的资源,OAuth2 Provider需要提供认证的API接口,用户通过账号密码来获取权限去访问被OAuth保护的资源,OAuth2 Provider 又可分为两部分:

  • Authorization Server(授权服务)
  • Resources Server(资源服务)

他们通常不在一个服务中,一个授权服务可以对应多个资源服务,资源服务也可以是授权服务。

OAuth2 Provider

Authorization Server(授权服务) 配置

//授权服务
    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
        //@Autowired
        //@Qualifier("dataSource")
        private DataSource dataSource;

        //配置将Token存储到内存
        private TokenStore tokenStore = new InMemoryTokenStore();
        //配置将Token存储到数据库
        //JdbcTokenStore tokenStore=new JdbcTokenStore(dataSource);

        //配置开启密码类型的验证,只有配置了才会开启
        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;

        @Autowired
        private UserService userServiceDetail;

        //配置客户端的基本信息
        @Override
        //配置客户端信息
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

            String finalSecret = new BCryptPasswordEncoder().encode("123456");

            clients.inMemory()
                    //客户端Id,在Authorization Server 是唯一的
                    .withClient("client-service")
                    //认证类型
                    //客户端模式
                    .authorizedGrantTypes("client_credentials", "password","refresh_token")
                    //权限范围
                    .scopes("server")
                    //权限信息
                    .authorities("oauth2")
                    //客户端密码
                    .secret(finalSecret)
                    //密码模式
                    .and().withClient("client_2")
                    .authorizedGrantTypes("password", "refresh_token")
                    .scopes("server")
                    .authorities("oauth2")
                    .secret(finalSecret)
                    .accessTokenValiditySeconds(2*3600);//2小时过期
        }

        @Override
        //配置Token节点的安全策略
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
            endpoints
                    .tokenStore(tokenStore)//Token的存储方式
                    //.tokenStore(new RedisTokenStore(redisConnectionFactory))
                    .authenticationManager(authenticationManager)//开启密码类型的验证
                    .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
                    //配置读取用户验证信息,获取用户认证信息的接口
                    .userDetailsService(userServiceDetail);
            //endpoints.reuseRefreshTokens(true);
        }


        @Override
        //配置授权Token的节点和Token服务
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
            //配置获取Token的策略,允许表单认证,配置之后可通过表单获取Token
            oauthServer.allowFormAuthenticationForClients();
        }
    }

Spring Security 认证配置

@Configuration
@EnableWebSecurity//开启WebSecurity功能
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启方法上的保护
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.requestMatchers()
                .anyRequest()
                .and().authorizeRequests()
                //.antMatchers("/admin/**").authenticated()
                .antMatchers("/css/**", "/test","/oauth/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")///admin/**的URL都需要有超级管理员角色,如果使用.hasAuthority()方法来配置,需要在参数中加上ROLE_,如下.hasAuthority("ROLE_超级管理员")
                .anyRequest().authenticated();//其他的路径都是登录后即可访问
    }
    //配置验证管理的Bean
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

Resources Server(资源服务) 配置

//配置资源服务
    //@Configuration
    //@EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            //资源访问控制,可配置必须通过token认证过后才可以访问的资源,permitAll()表示不需要token可直接访问
            http
                    .authorizeRequests()
                    .antMatchers("/login").permitAll();
        }
    }
OAuth2 Client

客户端用来访问被 OAuth保护起来的资源,需要配置

  • Protected Resource Configuration(受保护的资源配置)
security:
  oauth2:
    resource:
      user-info-uri: http://localhost:8763/current

    client:
    # 客户端Id ,与OAuth Provider 中的配置一一对应
      clientId: client-service
      # 客户端密码,与OAuth Provider 中的配置一一对应
      clientSecret: 123456
      # 获取Token的节点
      accessTokenUri: http://localhost:8763/oauth/token
      grant-type: client_credentials,password
      # 客户端的域
      scope: server
  • Client Configuration(客户端配置)
@EnableOAuth2Client
@EnableConfigurationProperties
@Configuration
public class OAuth2ClientConfig {
    
    //配置受保护的资源信息
    @Bean
    @ConfigurationProperties(prefix = "security.oauth2.client")
    public ClientCredentialsResourceDetails clientCredentialsResourceDetails() {
        return new ClientCredentialsResourceDetails();
    }

    //配置过滤器,存储当前请求和上下文
    /*@Bean
    public RequestInterceptor oauth2FeignRequestInterceptor(){
        return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), clientCredentialsResourceDetails());
    }*/

    @Bean
    public OAuth2RestTemplate clientCredentialsRestTemplate() {
        return new OAuth2RestTemplate(clientCredentialsResourceDetails());
    }
}

也可以仅使用 @EnableOAuth2Client 简化配置。

在客户端开启资源服务,Spring Security 提供了认证过滤器,可对URL进行开放和拦截。

@Configuration
@EnableResourceServer//开启资源服务
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/student").permitAll();
    }
}

三.测试

配置完成后,我们可以通过 postMan 或者在浏览器上访问以下链接获取 Token

http://localhost:8763/oauth/token?username=123&password=123&grant_type=password&scope=server&client_id=client-service&client_secret=123456

携带 Token 即可访问受保护的资源

http://localhost:8762/hi?access_token=7e664c6b-b60f-4f1a-97c2-9dea092044c4

我的 Github:Github
CSDN : CSDN 博客
个人网站: 天狼星的博客
完整代码:Spring Cloud Finchley | Spring Cloud OAuth2
微信公众号:[Mr sirius]
参考<<深入理解Spring Cloud 与微服务构建>>

猜你喜欢

转载自blog.csdn.net/Sirius_hly/article/details/89855925