美文网首页
7、spring cloud OAuth2授权服务

7、spring cloud OAuth2授权服务

作者: KissGoodby | 来源:发表于2018-11-21 18:51 被阅读0次

    关于spring cloud OAuth2

    OAuth2是一个基于令牌的安全框架,允许用户使用第三方验证服务进行验证,如果用户成功通过了验证,则会获得一个令牌,该令牌必须与每个请求一起发送,然后验证服务对每次请求的令牌进行验证,确定这个令牌是否有权限访问。
    OAuth2将安全性分解为4个部分:

    • 受保护资源:这是开发人员想要保护的资源(在这里就是一个个微服务接口),需要确保通过验证并且具有访问权限的用户才能访问他
    • 资源所有者:就是哪些用户可以访问该服务,以及他们可以使用该服务完成哪些事情
    • 应用程序:这是代表用户调用服务的应用程序,毕竟用户是很少直接调用服务的,依赖应用程序为他们服务。
    • OAuth2验证服务器:是应用程序和保护资源之间的中间人,做身份的验证和授权

    在我们微服务框架中,为了保证微服务的对外安全,一般都会要为微服务接口做权限校验。这里spring为我们提供了开箱即用的OAuth2和Security。我们用代码简单的模拟一下。

    搭建OAuth2微服务授权应用

    这里我们先创建一个spring boot服务,作为OAuth2的验证服务。

    1. 创建OAuth2服务,添加maven依赖
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth</groupId>
                <artifactId>spring-security-oauth2</artifactId>
            </dependency>
    

    添加OAuth2和security依赖的jar

    1. 在启动类上添加@EnableAuthorizationServer@EnableResourceServer注解告诉spring boot这是一个OAuth2服务和受保护的资源。并且添加一个/user的端口,此端口由受保护服务调用,验证访问令牌和用户角色。
    @SpringBootApplication
    @RestController
    @EnableResourceServer
    @EnableAuthorizationServer
    public class SecuitryApplication {
    
        @RequestMapping(value = "/user", produces = "application/json")
        public Map<String, Object> user(OAuth2Authentication user) {
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("user", user.getUserAuthentication().getPrincipal());
            userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
            return userInfo;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(SecuitryApplication.class, args);
        }
    }
    
    1. 哪些服务可以使用服务
    @Configuration
    public class OAuth2Config extends AuthorizationServerConfigurerAdapter{
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        /**
         * 定义通过验证服务注册了哪些客户端应用程序
         * ClientDetailsServiceConfigurer 支持两种不同类型的存储:内存存储和JDBC存储
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("security")
                    .secret("hui")      // 注册应用程序的名称和秘钥
                    .authorizedGrantTypes("refresh_token", "password", "client_credentials")    // 授权类型,密码,客户端凭证
                    .scopes("webclient", "mobileclient");       //客户端操作的范围
        }
    
        /**
         * 使用默认的验证管理器和用户详细信息服务
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    .authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService);
        }
    }
    

    这里定义了OAuth2Config类,扩展了AuthorizationServerConfigurerAdapter类,基本都是用了默认配置

    1. 定义用户ID 密码和角色
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        @Bean
        protected UserDetailsService userDetailsService() {
            return super.userDetailsService();
        }
    
        /**
         * 定义用户名 密码和角色
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth
                    .inMemoryAuthentication()
                    .withUser("hui.wang").password("hui.wang").roles("USER")
                    .and()
                    .withUser("admin").password("admin").roles("USER", "ADMIN");
        }
    }
    

    这里也基本都是用了默认配置,仅仅定义了用户和角色

    1. 配置application文件
    spring:
      application:
        name: security-server
    server:
      port: 9090
      context-path: /auth
    
    
    eureka:
      instance:
        prefer-ip-address: true #注册服务的IP
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka
        register-with-eureka: true
    
    

    配置了context-path和注册eureka

    1. 启动服务,然后使用Post man来验证


      登录1
      登录2

      可以看到返回值:

    {
        "access_token": "3ca13458-6e6f-48b9-a7c9-13f329ca68ca",
        "token_type": "bearer",
        "refresh_token": "0635cc7f-521e-429b-99c2-37861d8c44c7",
        "expires_in": 43199,
        "scope": "webclient"
    }
    

    其中access_token是关键字段,调用收保护的资源必须携带的令牌

    使用OAuth服务

    1. consumer端和provider端都要添加maven
    <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-security</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.security.oauth</groupId>
                <artifactId>spring-security-oauth2</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-jwt</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-rsa</artifactId>
            </dependency>
    
    1. consumer端和provider端都要添加OAuth2的服务地址,在application中配置
    security:
      oauth2:
        resource:
           userInfoUri: http://localhost:9090/auth/user
    
    1. provider端配置为受保护的资源,添加@EnableResourceServer注解
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableResourceServer
    public class ProviderApplicatioin {
    
        public static void main(String[] args) {
            SpringApplication.run(ProviderApplicatioin.class, args);
        }
    }
    
    1. provider端配置访问权限
    @Configuration
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter{
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().authenticated();
        }
    }
    
    1. consumer 配置OAuth2RestTemplate,保证令牌可以传递给provider端
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableResourceServer
    public class ConsumerApplication {
    
        @Bean
        public OAuth2RestTemplate auth2RestTemplate(OAuth2ClientContext oauth2ClientContext,
                OAuth2ProtectedResourceDetails details) {
            return new OAuth2RestTemplate(details, oauth2ClientContext);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class, args);
        }
    }
    

    这个时候调用consumer端服务的时候需要在header里面添加Authorization字段,值为字符串Bearer + access_token中间有一个空格

    image.png

    相关文章

      网友评论

          本文标题:7、spring cloud OAuth2授权服务

          本文链接:https://www.haomeiwen.com/subject/sunxqqtx.html